Apache Hive

Hive — SQL-слой поверх Hadoop/HDFS: пишете HQL (почти как SQL), а запросы превращаются в MapReduce/Spark-задачи. Классика warehouse-аналитики.

Уровень: средний 18 разделов ⏱ 2–3 часа

1. Что такое Hive

Hive хранит метаданные таблиц в Hive Metastore (обычно отдельная БД), а сами данные — на HDFS (или S3). Запрос компилируется в задачу: классически MapReduce, современней — Tez/Spark.

Сегодня Hive вытесняется Spark SQL и Presto, но метастор и HQL-опыт остаются важными.

2. Схема типов запросов

ИнструментТип работы
HiveETL и пакетные batch-задачи
Presto/Trinoинтерактивные запросы (OLAP)
Spark SQLгибрид: batch + streaming + ML

3. Основные команды HQL

SHOW DATABASES;
USE analytics;

CREATE TABLE events (
    ts TIMESTAMP,
    user_id INT,
    event STRING
)
PARTITIONED BY (dt STRING)
STORED AS PARQUET;

SHOW TABLES;
DESCRIBE events;

4. Загрузка данных

INSERT INTO TABLE events PARTITION (dt='2026-09-05')
SELECT ts, user_id, event FROM staging;

LOAD DATA INPATH 'hdfs:///input/events.csv'
INTO TABLE events PARTITION (dt='2026-09-05');

Внешние таблицы (EXTERNAL) не удаляют данные при DROP — удобно для данных в S3.

5. Запросы

SELECT
    dt,
    count(*) AS n,
    count(DISTINCT user_id) AS users
FROM events
WHERE event = 'buy' AND dt >= '2026-09-01'
GROUP BY dt
ORDER BY n DESC;

Оконные функции, CTE, join — поддерживаются, как в обычном SQL (см. SQL).

6. Партиционирование

Партиция — папка в HDFS по колонке (dt, country): запросы по партициям читают только нужные файлы. Эффект сильнее на больших данных, чем индексы.

Статическая партиция указывается в INSERT; динамическая — SET hive.exec.dynamic.partition=true с проекцией через SELECT.

7. Bucketing

CREATE TABLE events_bucketed (
    ...same columns...
)
CLUSTERED BY (user_id) INTO 16 BUCKETS
STORED AS ORC;

Bucket'и фиксируют порядок строк по хешу колонки — ускоряют джойны и sampling.

8. Оптимизация

9. Metastore и интеграции

Hive Metastore — общий каталог для всей экосистемы: таблицы, созданные в Hive, видны в Spark SQL, Presto, схемы для Zeppelin.

10. Лучшие практики

Запрос с джойном двух огромных несверхсложных ключей может превратиться в shuffle на весь кластер — совпадай партиции/бакеты по ключу джойна.

11. ACID и транзакции в Hive

Долгое время Hive считался чисто пакетным инструментом без поддержки транзакций. Начиная с Hive 3 ситуация изменилась: таблицы, хранящиеся в формате ORC с параметром transactional=true, поддерживают операции INSERT, UPDATE и DELETE с частичной изоляцией.

Механика выглядит так:

ALTER TABLE events COMPACT 'major';
SHOW TRANSACTIONS;
SHOW COMPACTIONS;
Транзакционные таблицы требуют формата ORC и настроенного метастора на реляционной базе. Без транзакций строку можно изменить только перезаписью данных через INSERT OVERWRITE.

12. Пользовательские функции: UDF, UDAF, UDTF

Когда встроенных функций не хватает, пишут собственные расширения. В Hive их три типа:

ТипЧто делаетОдин вызов
UDFодна строка → одно значениеmy_clean_string()
UDAFгруппа строк → одно значениеmy_median()
UDTFодна строка → несколько строкmy_explode_json()

Быстрый путь без компиляции — скрипты через TRANSFORM:

ADD FILE mapper.py;

SELECT TRANSFORM (event, user_id)
       USING 'python3 mapper.py'
       AS (event STRING, clean_id INT)
FROM events;

Скомпилированный JAR подключается командами:

ADD JAR /tmp/my-udf.jar;
CREATE TEMPORARY FUNCTION clean AS
       'com.example.udf.CleanString';
Для простых преобразований используй встроенные regexp_extract и json_tuple: они быстрее и не требуют перекомпиляции кластера.

13. Диагностика и план запроса

Перед оптимизацией полезно понять, во что Hive превратит ваш запрос. Команда EXPLAIN показывает логический и физический план исполнения, включая количество Map/Reduce-стадий.

EXPLAIN SELECT dt, count(*)
FROM events
WHERE dt >= '2026-09-01'
GROUP BY dt;

Оптимизатор принимает решения по статистике, поэтому её нужно собирать после массовых загрузок:

ANALYZE TABLE events COMPUTE STATISTICS;
ANALYZE TABLE events PARTITION (dt)
COMPUTE STATISTICS FOR COLUMNS;
Планы и метрики запросов удобно сравнивать после каждого «тюнинга»: план до, план после, замер реального времени.

14. Работа в YARN и планировщиках

Задачи Hive исполняются как приложение YARN. Ресурсы кластера делятся планировщиками: Capacity Scheduler (по умолчанию) и Fair Scheduler. Понимание очередей важно, когда ваши запросы конкурируют с запросами других команд.

SET mapreduce.job.queuename=analytics;
SET hive.exec.parallel=true;
SET hive.exec.parallel.thread.number=8;
SET mapreduce.reduce.memory.mb=4096;
ПараметрЭффект
mapreduce.job.queuenameочередь, откуда брать ресурсы
hive.exec.parallelнезависимые стадии бегут одновременно
mapreduce.reduce.memory.mbлимит памяти редьюсеров
Не раздувай память контейнеров без предела: задача с лимитом выше квоты очереди будет бесконечно перезапускаться. Следи за метриками в Resource Manager.
Баланс простой: больше памяти на контейнер — быстрее задача, но меньше параллельных задач помещается на кластер.

15. Работа с JSON и вложенными типами

Логи и выгрузки из API почти всегда приходят в JSON. Hive умеет хранить вложенные структуры как есть — STRUCT, ARRAY и MAP, — а разбирать JSON-строки помогают встроенные функции.

SELECT
    get_json_object(payload, '$.user.id')   AS user_id,
    json_tuple(payload, 'event', 'price')
FROM events;

Для массива внутри строки удобен LATERAL VIEW explode() — одна строка превращается во много:

SELECT tag, count(*) AS cnt
FROM events
LATERAL VIEW explode(tags) t AS tag
GROUP BY tag;
ТипСинтаксисДоступ
STRUCTstruct<id:int>col.id
ARRAYarray<string>col[0]
MAPmap<string,int>col['key']
Для единичных полей предпочтительнее разворачивать JSON на этапе загрузки (INSERT ... SELECT), а не на каждый запрос — так парсинг происходит один раз.
Избегайте get_json_object на огромных таблицах без фильтра: парсинг Regex-ом выполняется на каждой строке и обходит партиции.

16. Облачные хранилища и внешние таблицы

В современных деплоях данные лежат не в HDFS, а в объектном хранилище — S3, ADLS или GCS. Внешняя таблица позволяет читать их без копирования на кластер.

CREATE EXTERNAL TABLE events (
    dt STRING,
    event STRING
)
STORED AS PARQUET
LOCATION 's3a://analytics/events';
ХранилищеПротоколОсобенность
AWS S3s3a://самый распространённый
Azure Data Lakeabfss://интеграция с ADLS Gen2
Google Cloudgs://через GCS коннектор
Включайте блокирующий кеш: промежуточные результаты в S3 переживают перезапуск запроса и заметно ускоряют повторные вычисления.
Объектные хранилища платные за каждый GET. Фильтруйте и проектируйте читаемые колонки — дорого именно скачивание, а не вычисление.

17. Потоковая загрузка: Kafka и микро-батчи

Пакетный Hive медленно реагирует на события, поэтому «горячие» данные сначала попадают в Kafka, а затем льются в Hive микро-батчами.

-- Spark Structured Streaming в Hive-таблицу
df.writeStream
    .format("hive")
    .option("table", "events_stream")
    .outputMode("append")
    .trigger(Trigger.ProcessingTime("1 minute"))
    .start();

Микро-батч раз в 1–5 минут сглаживает нагрузку и даёт точность «почти реального времени» без сложностей полноценного стриминга.

Подробнее о Kafka — в курсе Kafka, о стриминге — в Apache Spark.

18. Безопасность: Ranger, Kerberos и шифрование

Данные в Hive часто чувствительны: доступ должен быть и по гранулярности, и по журналированию. Стандартный стек — Apache Ranger + Kerberos.

-- пример политики Ranger: 
-- пользователь analyst может SELECT из db1.events, 
-- но не из db1.payments
Начинайте с «минимум прав»: у аналитика — чтение витрин, у ETL-сервиса — запись в staging, у админа — всё. Легче выдать дополнительный доступ, чем отозвать утёкший.
Шифрование «на лету» (Transparent Data Encryption) и TLS между узлами включайте до загрузки чувствительных данных, а не после инцидента.

19. Форматы файлов и сжатие: ORC, Parquet, Avro

То, как Hive хранит данные, влияет на скорость и объём сильнее, чем большинство настроек запросов. Современный дефолт — колоночные форматы ORC и Parquet: они читают только нужные колонки и хорошо сжимаются.

CREATE TABLE events (
  user_id BIGINT, url STRING, ts TIMESTAMP
)
STORED AS ORC
TBLPROPERTIES ('orc.compress'='SNAPPY');
Проверьте эффект на своих данных: колоночные форматы ускоряют COUNT и агрегации, а выделение узких колонок уменьшает ввод-вывод в разы.
Не меняйте формат продакшн-таблицы «на живую»: создайте новую таблицу, скопируйте данные через INSERT OVERWRITE, затем переименуйте. Иначе запросы в момент копирования будут читать полупустые таблицы.

20. Стратегии джойнов: MapJoin, Sort Merge и Skew

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

СтратегияКогдаОсобенность
MapJoinмаленькая таблицазагружается в память маппера
Sort Mergeобе таблицы большиетребует сортировки по ключу
Skew Join«горячие» ключиизолирует поляризованные значения
SET hive.auto.convert.join=true;
SET hive.optimize.skewjoin=true;
-- принудительная подсказка MapJoin:
SELECT /*+ MAPJOIN(dim) */ ...
FROM fact f JOIN dim d ON f.dim_id = d.id;
Сравнивайте планы до и после подсказок через EXPLAIN: иногда «очевидное» ускорение ухудшает результат из-за смещения кардинальности.
MapJoin «съедает» память мапперов: слишком большая правая таблица уронит задачи. Проверяйте размер через статистику таблицы или FILESYSTEM перед подсказкой.

21. Дата и время в HQL: функции и форматирование

Даты в Hive хранятся как DATE или TIMESTAMP, а строки часто приходят в произвольных форматах. Функции преобразования и арифметики экономят часы ручной возни с данными.

SELECT current_timestamp(),
       from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm'),
       to_date('2026-09-19 10:00:00'),
       datediff('2026-09-19', '2026-01-01'),
       date_add('2026-09-19', 7);  -- плюс 7 дней
Храните события в TIMESTAMP с часовым поясом и приводите к UTC на входе — иначе отчёты «поедут» при переводе часов.
Для интервальных расчётов по календарю используйте date_trunc ('month', 'quarter') — мощная альтернатива ручной арифметике.

22. Автоматизация Hive: beeline-скрипты и PyHive

Повседневные задачи — пересчёт витрин, обновление партиций, отправка отчётов — легко оборачиваются в сценарии поверх стандартного клиента beeline.

beeline -u jdbc:hive2://hs2:10000/default \
  -f daily_refresh.sql --hivevar date=2026-09-19

-- внутри daily_refresh.sql
INSERT OVERWRITE TABLE mart.daily
PARTITION (dt = '${hivevar:date}')
SELECT ... FROM events WHERE ts = '${hivevar:date}';
Заведите «точки контроля»: после каждого скрипта пишите метку в таблицу состояний — так сразу видно, где встал конвейер.
Не хардкодьте креденшелы в скрипты: используйте Kerberos-клок или секреты из Vault/KMS, как описано в разделе 18.

Что дальше

Интерактивная аналитика по тем же данным — в уроке Presto, визуальный слой — Zeppelin, движок — Spark.

← Вернуться к курсам