Оптимизация запросов на соединение улья - PullRequest
3 голосов
/ 12 апреля 2020
Table A
---------
col1, col2,Adate,qty

Table B
-------
col2,cost,Bdate

Размеры таблиц следующие:

A: 1 миллион B: 700k

Рассмотрим этот запрос:

SELECT 
  A.col1,
  A.col2,
  B.Bdate bdate,
  SUM(qty)*COLLECT_LIST(cost)[0] price 
FROM A 
JOIN B 
ON (A.col2 = B.col2 AND A.Adate <= B.Bdate) 
GROUP BY 
  A.col1,
  A.col2,
  B.bdate;

Приведенный выше запрос улья занимает более 3 часов в кластере из 4 подчиненных (8 ГБ памяти, 100 ГБ диска) и 1 главного (16 ГБ памяти, 100 ГБ диска)

Можно ли оптимизировать этот запрос? Если да, где возможна оптимизация?

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Используйте Tez и mapjoin.

set hive.auto.convert.join=true; --this enables map-join
set hive.mapjoin.smalltable.filesize=25000000; --adjust for your smaller table to fit in memory
set hive.execution.engine=tez;

Также это вычисление неэффективно для памяти:

SUM(qty)*COLLECT_LIST(cost)[0] price 

COLLECT_LIST соберет все значения стоимости в группе в неуникальные ( содержит значения из ВСЕХ строк в группе ) и неупорядоченный (да, неупорядоченный, потому что у вас нет какого-либо массива distre + sort до collect_list). Этот массив может быть достаточно большим (количество элементов = количество строк в группе), в зависимости от ваших данных, тогда вы берете элемент [0], это означает, что вы выбираете любую произвольную стоимость из группы. Имеет ли смысл собирать массив, чтобы получить какой-либо случайный элемент? Вместо этого используйте min() или max. Если не имеет значения, какой cost должен быть взят, тогда min(cost) или max(cost) или какая-либо другая скалярная функция будет занимать меньше памяти. Вы можете использовать функцию first_value analyti c (может потребоваться подзапрос, но это также будет эффективно для использования памяти)

1 голос
/ 12 апреля 2020

Я постараюсь дать вам несколько советов по улучшению производительности запросов в Hive.

  • Проверьте используемый вами механизм выполнения
set hive.execution.engine;

Если вы используете механизм выполнения Если вы используете mr, то вместо MapReduce вы можете использовать Apache Spark или Apache Tez, которые работают быстрее, чем MapReduce.

set hive.execution.engine=tez;
  • Запросы на соединение являются вычислительно дорогими и могут быть медленными, особенно когда вы объединяете три или более таблиц или работаете с очень большими данными.

Одна из стратегий, которую можно использовать для решения этой проблемы, - это заранее объединить данные и сохранить предварительно объединенный результат в отдельной таблице, которую можно затем запросить. это один из способов денормализации нормализованной базы данных, чтобы упростить выполнение аналитических c запросов. Такой подход к предварительному объединению таблиц сопряжен с некоторыми затратами, но он может упростить написание аналитических c запросов и ускорить их выполнение.

Существуют и другие методы повышения производительности запросов Hive

  • Порядок таблицы соединений (самая большая таблица в прошлом)

Как и при любом типе настройки, он важно понимать внутреннюю работу системы. Когда Hive выполняет соединение, ему нужно выбрать, какая таблица передается в потоковом режиме, а какая таблица кэшируется. Hive берет последнюю таблицу в операторе JOIN для потоковой передачи, поэтому мы должны убедиться, что эта потоковая таблица является самой большой среди двух.

A: 1 миллион B: 700k

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

  • Bucketing хранит данные в отдельных файлах, а не в отдельных подкаталогах, таких как разделы.

Он делит данные практически случайным образом, а не предсказуемым образом, как разделение. Когда записи вставляются в объединенную таблицу, Hive вычисляет коды ha sh значений в указанном столбце группирования и использует эти коды ha sh для разделения записей на сегменты. По этой причине группирование иногда называют разделением ha sh. Цель группирования - равномерно распределить записи по заранее определенному количеству сегментов. Группирование может улучшить производительность объединений, если все объединенные таблицы объединены в столбец ключа объединения.

Подробнее о объединении см. На странице руководства по языку Hive с описанием таблиц с объединением,

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL+BucketedTables?.

https://data-flair.training/blogs/bucketing-in-hive/

Разделение

  • Разделение - это способ разделения таблицы на связанные части на основе значений отдельных столбцов, таких как дата, город и отдел.

Каждая таблица в кусте может иметь один или несколько ключей разделов для идентификации конкретного раздела. Используя раздел, можно легко выполнять запросы к фрагментам данных.

https://data-flair.training/blogs/apache-hive-partitions/

Надеюсь, это может быть полезно!

С уважением.

...