Настройка производительности запроса Hive

У меня есть запрос Hive, который выбирает около 30 столбцов и около 400 000 записей и вставляет их в другую таблицу. Я одна вступить в мое выражение SQL, которое просто внутреннее соединение.

запрос завершается с ошибкой из-за превышения предела накладных расходов JAVA GC.

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

Я довольно новичок в Hive. Я не могу понять почему это соединение вызывает исключения памяти.

есть ли что-то, что я должен знать о том, как я пишу запросы Hive, чтобы они не вызывали эти проблемы? Может ли кто-нибудь объяснить, почему соединение может вызвать эту проблему, но выбор большего объема данных и того же количества столбцов не делает.

ценю ваши мысли по этому поводу. Спасибо

2 ответов


в зависимости от версии Hive и конфигурации, ответ на ваш вопрос может варьироваться. Было бы проще, если бы вы могли поделиться своим точным запросом вместе с инструкциями create двух таблиц и оценкой их размеров.

чтобы лучше понять проблему, давайте рассмотрим, как "обычный" внутреннее соединение работает в улье.

Hive присоединиться к MapReduce:

вот упрощенное описание того, как внутренний join in Hive компилируется в MapReduce. В общем случае, если у вас есть две таблицы t1 и t2 с запросом соединения, например:

SELECT
   t1.key, t1.value, t2.value
FROM
   t1
   JOIN
   t2 (ON t1.key = t2.key);

где, t1 имеет следующее содержание:

k_1    v1_1
k_2    v1_2
k_3    v1_3    

где, t2 имеет следующее содержание:

k_2    v2_2
k_3    v2_3
k_4    v2_4    

мы ожидаем, что результат соединения будет

k_2    v1_2    v2_2
k_3    v1_3    v2_3

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

для t1:

k_1, <v1_1, t1>
k_2, <v1_2, t1>
k_3, <v1_3, t1>

для t2:

k_2, <v2_2, t2>
k_3, <v2_3, t2>
k_4, <v2_4, t2>

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

в приведенном выше примере мы получим следующие группировки:

k_1, <<v1_1, t1>>
k_2, <<v1_2, t1>, <v2_2, t2>>
k_3, <<v1_3, t1>, <v2_3, t2>>
k_4, <<v2_4, t2>>

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

для k_1 нет значения из t2, и ничего не испускается.

для k_2 умножение значений испускается-k_2, v1_2, v2_2 (так как из каждой таблицы есть одно значение, 1x1 = 1)

для k_3 испускается умножение значений-k_3, v1_3, v2_3 (так как из каждой таблицы есть одно значение, 1x1 = 1)

для k_4 нет значения из t1, и ничего не испускается. Следовательно, вы получаете результат, который ожидали от своего внутреннего соединения.

ок, так что мне делать?

  1. возможно что перекос в вашем данные. Другими словами, когда редуктор получает данные, список значений, соответствующих некоторому ключу, очень длинный, что вызывает ошибку. Чтобы облегчить проблему, вы можете попробовать увеличить объем памяти, доступной для JVM. Вы можете сделать это, установив mapred.child.java.opts значение -Xmx512M в вашем улье-сайте.XML. Вы можете запросить текущее значение этого параметра, выполнив set mapred.child.java.opts; в вашем улье оболочки.

  2. вы можете попробовать использовать альтернативы "регулярному" соединению, например, map join. Вышеупомянутое объяснение соединений применяется к регулярным соединениям, где соединение происходит в редукторах. В зависимости от используемой версии Hive, Hive может автоматически конвертировать обычное соединение в map join, что быстрее (поскольку соединение происходит на этапе карты). Чтобы включить оптимизацию, установите hive.auto.convert.join to true. Это свойство было введено в куст 0.7

  3. в дополнение к установке hive.auto.convert.join to true, вы также можете установить hive.optimize.skewjoin to true. Это позволит устранить перекос в вашей проблеме, описанной в 1.


большое спасибо за ответ Марк. Ценится.

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

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

см. самую большую таблицу последней на http://hive.apache.org/docs/r0.9.0/language_manual/joins.html

Ваше объяснение выше-это очень полезно. Большое Спасибо