Оптимизация запросов Apache в Hive в Azure HDInsight

В этой статье описываются некоторые популярные способы оптимизации производительности, которые можно использовать для повышения производительности запросов Apache Hive.

Выбор типа кластера

В Azure HDInsight можно выполнять запросы Apache Hive на нескольких разных типах кластеров.

Выберите подходящий тип кластера, чтобы оптимизировать производительность конкретной рабочей нагрузки.

  • Выберите тип кластера Интерактивные запросы для оптимизации интерактивных запросов ad hoc.
  • Выберите тип кластера Apache Hadoop, чтобы оптимизировать его для запросов Hive, используемых в качестве пакетной обработки.
  • Типы кластеров Spark и HBase также могут выполнять запросы Hive и могут быть подходящими при выполнении этих рабочих нагрузок.

Дополнительные сведения о выполнении запросов Hive в различных типах кластеров HDInsight см. в статье "Что такое Apache Hive и HiveQL в Azure HDInsight?

Горизонтальное масштабирование рабочих узлов

Увеличение числа рабочих узлов в кластере HDInsight позволяет выполнять больше мапперов и редьюсеров параллельно. В HDInsight можно увеличить масштаб двумя способами.

  • Количество рабочих узлов можно указать при создании кластера с помощью портала Azure, Azure PowerShell или интерфейса командной строки. Дополнительные сведения см. в статье Создание кластеров Hadoop в HDInsight. На следующем снимке экрана показана рабочая конфигурация узла на портале Azure:

    размер узлов кластера в портале Azure.

  • После создания кластера можно также изменить количество рабочих узлов, чтобы горизонтально увеличить масштаб кластера без необходимости его повторного создания.

    Масштабирование размера кластера в Azure Portal.

Дополнительные сведения о масштабировании HDInsight см. в статье Масштабирование кластеров HDInsight.

Использование Apache Tez вместо Map Reduce

Apache Tez — это механизм выполнения, альтернативный механизму MapReduce. Кластеры HDInsight на базе Linux имеют включенную по умолчанию платформу Tez.

Схема обзора Apache Tez в HDInsight.

Tez работает быстрее, так как:

  • Выполнить направленный ациклический граф (DAG) как одно задание в движке MapReduce. DAG требует, чтобы за каждым набором мапперов следовал набор редьюсеров. Это требование приводит к созданию множества заданий MapReduce для каждого запроса Hive. Tez не имеет такого ограничения и может обрабатывать сложные графы DAG как единое задание, сводя к минимуму затраты на создание новых заданий.
  • Позволяет избежать ненужных операций записи. Чтобы обработать тот же запрос Hive в механизме MapReduce, используются несколько заданий. Выходные данные каждого задания MapReduce записываются в HDFS для промежуточных данных. Так как Tez использует минимальное количество заданий для каждого запроса Hive, вы сможете избежать ненужных операций записи.
  • Сводит к минимуму задержки при загрузке. Tez лучше справляется с задачей минимизации задержки при запуске за счет уменьшения количества мапперов, необходимых для запуска, и улучшению оптимизации всего процесса.
  • Повторно использует контейнеры. Чтобы снизить задержки на запуск контейнеров, Tez всегда, где это возможно, использует контейнеры повторно.
  • Применяет методы непрерывной оптимизации. Традиционно оптимизация выполняется на этапе компиляции. Однако по мере поступления дополнительных сведений о входных данных появляется возможность улучшить оптимизацию уже на этапе работы. Tez применяет методы непрерывной оптимизации, что позволяет производить дальнейшую оптимизацию плана на этапе работы.

Дополнительные сведения об этих концепциях см. в разделе Apache TEZ.

Вы можете сделать любой запрос Hive с поддержкой Tez, добавив префикс к запросу с помощью следующей команды SET:

set hive.execution.engine=tez;

Секционирование данных в Hive

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

Секционирование данных в Hive реализуется путем реорганизации необработанных данных в новые каталоги. Каждой секции присвоен собственный каталог файлов. Пользователь определяет секционирование. Следующая схема иллюстрирует секционирование таблицы Hive по столбцу Год. Для каждого года создается новый каталог.

Секционирование Apache Hive в HDInsight.

Некоторые соображения секционирования:

  • Не создавайте недостаточно секций — Секционирование по столбцам с небольшим количеством значений может привести к созданию малого количества секций. Например, разделение по гендеру создает только две группы ("мужская" и "женская"), что позволяет сократить задержку максимум наполовину.
  • Секций не должно быть слишком много. С другой стороны, создание секции по столбцу с уникальным значением (например, содержащим идентификатор пользователя userid) приведет к появлению множества секций, Чрезмерная разбивка вызывает сильное напряжение на узел имен кластера, так как ему приходится обрабатывать большое количество каталогов.
  • Избегайте неравномерного распределения данных — выбирайте ключ секционирования рационально, таким образом, чтобы все секции были одинакового размера. Например, секционирование в столбце Штат может исказить распределение типов данных. Поскольку население штата Калифорния почти в 30 раз больше, чем в Вермонте, размер раздела может быть потенциально диспропорциональным, и производительность может значительно варьироваться.

Чтобы выполнить секционирование таблицы, используйте команду Секционирована по :

CREATE TABLE lineitem_part
      (L_ORDERKEY INT, L_PARTKEY INT, L_SUPPKEY INT,L_LINENUMBER INT,
      L_QUANTITY DOUBLE, L_EXTENDEDPRICE DOUBLE, L_DISCOUNT DOUBLE,
      L_TAX DOUBLE, L_RETURNFLAG STRING, L_LINESTATUS STRING,
      L_SHIPDATE_PS STRING, L_COMMITDATE STRING, L_RECEIPTDATE STRING,
      L_SHIPINSTRUCT STRING, L_SHIPMODE STRING, L_COMMENT STRING)
PARTITIONED BY(L_SHIPDATE STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;

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

  • Статическое секционирование означает, что сегментированные данные уже находятся в соответствующих каталогах. С помощью статических секций вы добавляете секции Hive вручную, исходя из расположения каталога. Просмотрите пример в следующем фрагменте кода:

    INSERT OVERWRITE TABLE lineitem_part
    PARTITION (L_SHIPDATE = '5/23/1996 12:00:00 AM')
    SELECT * FROM lineitem
    WHERE lineitem.L_SHIPDATE = '5/23/1996 12:00:00 AM'
    
    ALTER TABLE lineitem_part ADD PARTITION (L_SHIPDATE = '5/23/1996 12:00:00 AM')
    LOCATION 'wasb://sampledata@ignitedemo.blob.core.windows.net/partitions/5_23_1996/'
    
  • Динамическое секционирование означает, что Hive автоматически создаст секции для вас. Так как таблица секционирования уже была создана из промежуточной таблицы, теперь достаточно только выполнить вставку данных в секционированную таблицу:

    SET hive.exec.dynamic.partition = true;
    SET hive.exec.dynamic.partition.mode = nonstrict;
    INSERT INTO TABLE lineitem_part
    PARTITION (L_SHIPDATE)
    SELECT L_ORDERKEY as L_ORDERKEY, L_PARTKEY as L_PARTKEY,
         L_SUPPKEY as L_SUPPKEY, L_LINENUMBER as L_LINENUMBER,
         L_QUANTITY as L_QUANTITY, L_EXTENDEDPRICE as L_EXTENDEDPRICE,
         L_DISCOUNT as L_DISCOUNT, L_TAX as L_TAX, L_RETURNFLAG as L_RETURNFLAG,
         L_LINESTATUS as L_LINESTATUS, L_SHIPDATE as L_SHIPDATE_PS,
         L_COMMITDATE as L_COMMITDATE, L_RECEIPTDATE as L_RECEIPTDATE,
         L_SHIPINSTRUCT as L_SHIPINSTRUCT, L_SHIPMODE as L_SHIPMODE,
         L_COMMENT as L_COMMENT, L_SHIPDATE as L_SHIPDATE FROM lineitem;
    

Дополнительные сведения см. в разделе о секционированных таблицах.

Используйте формат ORC-файлов

Hive поддерживает различные форматы. Например:

  • Текст: формат файла по умолчанию работает с большинством сценариев.
  • Avro: хорошо подходит для сценариев взаимодействия.
  • ORC/Parquet: лучше всего подходит для повышения производительности.

Формат ORC (Optimized Row Columnar) — это очень эффективный способ хранения данных Hive. По сравнению с другими форматами ORC имеет следующие преимущества:

  • поддержка сложных типов, включая типы "ДатаВремя", а также сложные и полуструктурированные типы;
  • обеспечивает показатель сжатия данных до 70 %;
  • индексирует каждые 10 000 строк, что позволяет пропускать строки;
  • обеспечивает значительное снижение времени выполнения программы.

Чтобы активировать ORC формат, необходимо сначала создать таблицу командой Хранение в виде ORC:

CREATE TABLE lineitem_orc_part
      (L_ORDERKEY INT, L_PARTKEY INT,L_SUPPKEY INT, L_LINENUMBER INT,
      L_QUANTITY DOUBLE, L_EXTENDEDPRICE DOUBLE, L_DISCOUNT DOUBLE,
      L_TAX DOUBLE, L_RETURNFLAG STRING, L_LINESTATUS STRING,
      L_SHIPDATE_PS STRING, L_COMMITDATE STRING, L_RECEIPTDATE STRING,
      L_SHIPINSTRUCT STRING, L_SHIPMODE STRING, L_COMMENT      STRING)
PARTITIONED BY(L_SHIPDATE STRING)
STORED AS ORC;

Далее необходимо выполнить вставку данных в таблицу ORC из промежуточной таблицы. Например:

INSERT INTO TABLE lineitem_orc
SELECT L_ORDERKEY as L_ORDERKEY,
         L_PARTKEY as L_PARTKEY ,
         L_SUPPKEY as L_SUPPKEY,
         L_LINENUMBER as L_LINENUMBER,
         L_QUANTITY as L_QUANTITY,
         L_EXTENDEDPRICE as L_EXTENDEDPRICE,
         L_DISCOUNT as L_DISCOUNT,
         L_TAX as L_TAX,
         L_RETURNFLAG as L_RETURNFLAG,
         L_LINESTATUS as L_LINESTATUS,
         L_SHIPDATE as L_SHIPDATE,
         L_COMMITDATE as L_COMMITDATE,
         L_RECEIPTDATE as L_RECEIPTDATE,
         L_SHIPINSTRUCT as L_SHIPINSTRUCT,
         L_SHIPMODE as L_SHIPMODE,
         L_COMMENT as L_COMMENT
FROM lineitem;

Вы можете прочесть подробнее о формате ORC на странице руководства по языку Apache Hive.

Векторизация

Векторизация позволяет Hive обрабатывать пакеты из 1024 строк одновременно вместо обработки каждой строки отдельно. Это означает, что простые операции будут выполняться быстрее благодаря меньшему объему внутреннего кода, необходимого для запуска.

Чтобы активировать функцию векторизации, создайте запрос Hive со следующими параметрами:

set hive.vectorized.execution.enabled = true;

Для получения дополнительных сведений обратитесь к разделу Выполнение векторизованного запроса.

Другие методы оптимизации

Существуют дополнительные методы оптимизации, которые также можно использовать, например:

  • Бакетизация в Hive — метод, который позволяет разбиение или сегментирование больших наборов данных для оптимизации производительности запросов.
  • Оптимизация объединений — это процесс оптимизации выполнения запросов в Hive, направленный на повышение эффективности объединений и уменьшение необходимости в пользовательских подсказках. Для получения дополнительных сведений обратитесь к разделу Оптимизация объединений.
  • Увеличить редукторы.

Следующие шаги

В этой статье вы узнали некоторые распространенные методы оптимизации запросов Hive. Дополнительные сведения см. в следующих разделах: