Количество файлов, сгенерированных во время 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