Укажите минимальное количество сгенерированных файлов из Hive insert - PullRequest
2 голосов
/ 27 марта 2019

Я использую Hive в AWS EMR, чтобы вставить результаты запроса в таблицу Hive, разбитую по дате. Хотя общий размер выходных данных каждый день одинаков, количество сгенерированных файлов варьируется, обычно от 6 до 8, но в некоторые дни он создает только один большой файл. Я перезапускаю запрос пару раз, просто на случай, если на число файлов влияет наличие узлов в кластере, но кажется, что это согласованно.

Так что мои вопросы (а) что определяет, сколько файлов генерируется и (б) есть ли способ указать минимальное количество файлов или (еще лучше) максимальный размер каждого файла?

1 Ответ

2 голосов
/ 27 марта 2019

Количество файлов, сгенерированных во время INSERT ... SELECT, зависит от количества процессов, запущенных на конечном редукторе (конечная вершина редуктора, если вы работаете на Tez), плюс байтов на настроенный редуктор.

Если таблица секционирована и не указан DISTRIBUTE BY, то в худшем случае каждый редуктор создает файлы в каждом разделе. Это создает высокое давление на редукторы и может вызвать исключение OOM.

Чтобы убедиться, что редукторы записывают только один файл раздела, добавьте DISTRIBUTE BY partition_column в конце вашего запроса.

Если объем данных слишком велик, и вы хотите, чтобы большее количество редукторов увеличивало параллелизм и создавало больше файлов на раздел, добавьте случайное число к распределению, например, с помощью этого: FLOOR(RAND()*100.0)%10 - оно будет распределять данные дополнительно случайные 10 блоков, поэтому в каждом разделе будет 10 файлов.

Наконец, ваше предложение INSERT будет выглядеть так:

INSERT OVERWRITE table PARTITION(part_col)
SELECT * 
  FROM src
DISTRIBUTE BY  part_col, FLOOR(RAND()*100.0)%10; --10 files per partition

Также этот параметр конфигурации влияет на количество сгенерированных файлов:

set hive.exec.reducers.bytes.per.reducer=67108864; 

Если у вас слишком много данных, Hive запустит больше редукторов для обработки не более bytes per reducer, указанных для каждого процесса редуктора. Чем больше редукторов - тем больше файлов будет сгенерировано. Уменьшение этого параметра может привести к увеличению числа работающих редукторов, и они создадут как минимум один файл на редуктор. Если столбец раздела отсутствует в distribute by, то каждый редуктор может создавать файлы в каждом разделе.

Если коротко, используйте

DISTRIBUTE BY  part_col, FLOOR(RAND()*100.0)%10 -- 10 files per partition

Если вам нужно 20 файлов на раздел, используйте FLOOR (RAND () * 100.0)% 20; - это гарантирует минимум 20 файлов на раздел, если у вас достаточно данных, но не гарантирует максимальный размер каждого файла.

Байт на настройку редуктора не гарантирует, что это будет фиксированное минимальное количество файлов. Количество файлов будет зависеть от общего размера данных / bytes.per.reducer. Этот параметр гарантирует максимальный размер каждого файла.

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

Также прочитайте этот ответ об использовании distribute by для равномерного распределения данных между редукторами: https://stackoverflow.com/a/38475807/2700344

...