2016-12-20 6 views
1

У меня есть следующие (очень простой) Улей запрос:Оптимизация Hive GROUP BY, когда строки сортируются

select user_id, event_id, min(time) as start, max(time) as end, 
     count(*) as total, count(interaction == 1) as clicks 
from events_all 
group by user_id, event_id; 

Таблица имеет следующую структуру:

user_id     event_id    time   interaction 
Ex833Lli36nxTvGTA1Dv juCUv6EnkVundBHSBzQevw 1430481530295 0 
Ex833Lli36nxTvGTA1Dv juCUv6EnkVundBHSBzQevw 1430481530295 1 
n0w4uQhOuXymj5jLaCMQ G+Oj6J9Q1nI1tuosq2ZM/g 1430512179696 0 
n0w4uQhOuXymj5jLaCMQ G+Oj6J9Q1nI1tuosq2ZM/g 1430512217124 0 
n0w4uQhOuXymj5jLaCMQ mqf38Xd6CAQtuvuKc5NlWQ 1430512179696 1 

Я знаю, за то, что строки сначала сортируются по user_id, а затем по event_id.

Вопрос: есть ли способ «намекнуть» движку «Улей» на оптимизацию запроса при сортировке строк? Цель оптимизации - избегать хранения всех групп в памяти, поскольку она необходима только для сохранения одной группы за раз.

Прямо сейчас этот запрос, запущенный в 6-узловой кластер Hadoop с пропускной способностью 16 ГБ, содержит примерно 300 ГБ данных, занимает около 30 минут и использует большую часть ОЗУ, задыхаясь от системы. Я знаю, что каждая группа будет маленькой, не более 100 строк на кортеж (user_id, event_id), поэтому я думаю, что оптимизированное выполнение, вероятно, будет иметь очень небольшой объем памяти, а также быть быстрее (так как нет необходимости замыкать групповые ключи).

+0

В качестве побочного примечания 'count (взаимодействие == 1)' работает не так, как я ожидал, считая только строки, которые имеют 1, но вместо этого возвращает то же самое, что и 'count (*)'. –

+1

Да. Агрегативные функции, включая COUNT, игнорировать (только) значения NULL и FALSE не являются NULL –

ответ

1

Создайте сортированный стол в виде ведра. Оптимизатор будет знать, что он отсортирован по метаданным. Смотрите пример здесь (Официальные документы): https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-BucketedSortedTables

Граф только взаимодействие = 1: count(case when interaction=1 then 1 end) as clicks - случай будет отмечать все строки с 1 или нулевым и рассчитывать только 1s.

+0

Спасибо @leftjoin. Несколько вещей: во-первых, мой стол - это внешняя таблица, есть ли способ заставить его работать? Во-вторых, поскольку это внешняя таблица, формат является фиксированным (значения, разделенные вкладками, \ n завершаемые строки), и у него нет разных терминаторов для групп и т. Д. Если не так много спросить, можете ли вы привести пример, используя конкретную структуру, которую я опубликовал? –

+0

@Alejandro Piad Читайте также: http://grokbase.com/t/hive/user/133xgs10cb/bucketing-external-tables – leftjoin

+0

Прошу прощения, но, похоже, вам нужно будет создать таблицу в квадратных скобках и вставить ее переписать, это не будет работать, если вы создадите внешнюю таблицу поверх существующих текстовых файлов. и для переноса данных потребуется много времени. – leftjoin