Hive - есть ли способ дальнейшей оптимизации запроса HiveQL?

Я написал запрос, чтобы найти 10 самых загруженных аэропортов в США с марта по апрель. Он производит желаемый результат, однако я хочу попытаться оптимизировать его.

Есть ли какие-либо специфичные для HiveQL оптимизации, которые можно применить к запросу? Является GROUPING SETS применимо здесь? Я новичок в Hive, и пока это самый короткий запрос, который я придумал.

SELECT airports.airport, COUNT(Flights.FlightsNum) AS Total_Flights
FROM (
SELECT Origin AS Airport, FlightsNum 
  FROM flights_stats
  WHERE (Cancelled = 0 AND Month IN (3,4))
UNION ALL
SELECT Dest AS Airport, FlightsNum 
  FROM flights_stats
  WHERE (Cancelled = 0 AND Month IN (3,4))
) Flights
INNER JOIN airports ON (Flights.Airport = airports.iata AND airports.country = 'USA')
GROUP BY airports.airport
ORDER BY Total_Flights DESC
LIMIT 10;

Столбцы таблицы следующие:

Аэропорты

|iata|airport|city|state|country|

Flights_stats

|originAirport|destAirport|FlightsNum|Cancelled|Month|

4 ответа

Решение

Отфильтруйте по аэропорту (внутреннее соединение) и выполните агрегирование перед UNION ALL, чтобы уменьшить набор данных, передаваемый в конечный редуктор агрегации. Подзапросы UNION ALL с объединениями должны выполняться параллельно и быстрее, чем объединение с большим набором данных после UNION ALL.

SELECT f.airport, SUM(cnt) AS Total_Flights
FROM (
      SELECT a.airport, COUNT(*) as cnt 
       FROM flights_stats f
            INNER JOIN airports a ON f.Origin=a.iata AND a.country='USA'
       WHERE Cancelled = 0 AND Month IN (3,4)
       GROUP BY a.airport
       UNION ALL
      SELECT a.airport, COUNT(*) as cnt
       FROM flights_stats f
            INNER JOIN airports a ON f.Dest=a.iata AND a.country='USA'
       WHERE Cancelled = 0 AND Month IN (3,4)
       GROUP BY a.airport
     ) f 
GROUP BY f.airport
ORDER BY Total_Flights DESC
LIMIT 10
;

Настройте mapjoins и включите параллельное выполнение:

set hive.exec.parallel=true;
set hive.auto.convert.join=true; --this enables map-join
set hive.mapjoin.smalltable.filesize=25000000; --size of table to fit in memory

Используйте Tez и векторизацию, настройте параллелизм мапперов и редукторов: /questions/31865237/vyipolnit-hive-query-s-parametrami-predlozheniya-in-parallelno/31865256#31865256

Это может помочь, если вы выполните агрегирование до union all:

SELECT a.airport, SUM(cnt) AS Total_Flights
FROM ((SELECT Origin AS Airport, COUNT(*) as cnt 
       FROM flights_stats
       WHERE (Cancelled = 0 AND Month IN (3,4))
       GROUP BY Origin
      ) UNION ALL
      (SELECT Dest AS Airport, COUNT(*) as cnt
       FROM flights_stats
       WHERE Cancelled = 0 AND Month IN (3,4)
       GROUP BY Dest
      )
     ) f INNER JOIN
     airports a
     ON f.Airport = a.iata AND a.country = 'USA'
GROUP BY a.airport
ORDER BY Total_Flights DESC
LIMIT 10;

Я не думаю, что ГРУППОВЫЕ НАБОРЫ применимы здесь, потому что вы группируете только по одному полю.

Из Apache Wiki: "Предложение GROUPING SETS в GROUP BY позволяет нам указать более одной опции GROUP BY в одном наборе записей".

Вы можете проверить это, но вы в случае, когда Союз может быть лучше, поэтому вам действительно нужно проверить это и вернуться:

SELECT airports.airport,
SUM(
  CASE 
     WHEN T1.FlightsNum IS NOT NULL THEN 1
     WHEN T2.FlightsNum IS NOT NULL THEN 1
     ELSE 0
  END 
  ) AS Total_Flights
FROM airports
LEFT JOIN (SELECT  Origin AS Airport, FlightsNum 
    FROM flights_stats
   WHERE (Cancelled = 0 AND Month IN (3,4))) t1 
 on t1.Airport = airports.iata
LEFT JOIN (SELECT Dest AS Airport, FlightsNum 
   FROM flights_stats
   WHERE (Cancelled = 0 AND Month IN (3,4))) t2
 on t1.Airport = airports.iata
GROUP BY airports.airport
ORDER BY Total_Flights DESC
Другие вопросы по тегам