Сжатие аналитических данных
1) Зачем сжимать аналитические данные
Сжатие уменьшает объем хранения и трафик, ускоряет сканы за счет меньшего IO и лучшей кэшируемости. Цена — CPU и (иногда) сложность обновлений. Цель — оптимум “IO↔CPU↔точность↔стоимость” под ваши SLO.
Базовые метрики:- Compression Ratio (CR) = `raw_size / compressed_size`.
- Scan Cost ≈ bytes_scanned / throughput_storage + cpu_decode_time`.
- Total Cost = `storage_cost + compute_cost + egress_cost`.
2) Слои, где живет сжатие
1. На уровне формата: Parquet/ORC/Avro (страницы/страйпы/колонки).
2. На уровне энкодинга колонки: Dictionary, RLE, Delta, FoR/Bit-packing, Gorilla/XOR.
3. На уровне кодека: ZSTD, Snappy, LZ4, Gzip.
4. На уровне запроса/движка: векторизация, пропуск страниц (min/max), bloom/zone-map.
5. На уровне хранения: tiered storage (hot/warm/cold), компакшн, page cache.
3) Колоночные форматы и их преимущества
Parquet: страницы по колонкам; поддержка словарей, RLE/Bit-packing, статистик min/max и null-count.
ORC: страйпы с индексами на стримах, bloom-фильтры; эффективен для долгих сканов.
Avro (row): удобно для стрима/логов, хуже для аналитических сканов.
Практика: для аналитики по умолчанию используйте Parquet/ORC, включайте column stats и dictionary там, где кардинальность низкая/средняя.
4) Энкодинги колонок (lossless)
Dictionary: заменяет значения индексами (идеален для низкой кардинальности).
RLE (Run-Length Encoding): повторяющиеся значения → (value, run). Хорош для сортированных/кластеризованных колонок.
Delta/Delta-of-Delta: хранит разности (числа/время).
FoR (Frame-of-Reference) + Bit-packing: значение = base + offset; offset упакован N битами.
Gorilla/XOR (Time-series): хранит XOR соседних значений с переменной длиной; хорош для метрик.
Nullable-битмаски: отдельный поток null’ов повышает CR.
Совет: предварительная кластеризация/сортировка по ключам фильтрации резко улучшает RLE/zone-maps и CR.
5) Кодеки общего назначения
ZSTD: лучший CR при умеренной цене CPU; поддерживает уровни 1–22. Универсальный выбор.
Snappy: быстрый, низкий CR; подходит для горячих данных с высокой частотой чтения.
LZ4: еще быстрее Snappy, схожий CR; часто — для стрима/логов/кэшей.
Gzip/Deflate: высокий CR, высокая цена CPU; редко оправдан в интерактивной аналитике.
Правило: горячий слой — Snappy/LZ4, теплый/холодный — ZSTD(level 3–7).
6) Временные ряды и логи
TSDB/колоночные БД: Gorilla/XOR, Delta-RLE-Bitmap, Sparse-run для редких сигналов.
Логи: JSON→Parquet + ZSTD; нормализуйте ключи и типы (не храните “строковый int”).
Downsampling и roll-ups (lossy): храните агрегаты по окнам (1m/5m/1h) в горячем слое; сырые — в холодном.
Sketch-структуры: HLL (кардинальность), TDigest/KLL (квантили), CMS (частоты) — компактные, но аппроксимационные.
7) Lossless vs Lossy (когда можно потерять точность)
Lossless — отчетность, финансы, аудит.
Lossy — мониторинг, A/B-аналитика на больших окнах, телеметрия (с явной маркировкой!).
Контроль качества: задать допустимую погрешность (например, P99 ±0.5 п.п.) и проверять ее в CI.
8) Партиционирование, страницы и компакшн
Партиции: по дате/региону/тенанту → меньше сканов, лучше CR.
Размер страницы/страйпа: 64–256 КБ на страницу, 64–512 МБ на файл — баланс между seek и CPU.
Компакшн: объединяйте мелкие файлы (small files problem) — выше CR и скорость.
Zone-maps/Bloom: ускоряют пропуски страниц; эффективны при сортировке по фильтрам.
9) Сжатие и шифрование/приватность
Порядок операций: сначала сжатие, потом шифрование. Иначе CR ≈ 1.
TDE/ат-rest не мешает CR (шифруется уже сжатый блок).
In-transit (TLS) не влияет на формат.
Маскирование/токенизация PII до сжатия сохраняет энтропию управляемой.
Осторожно с OPE/DET-шифрованием: может ухудшать CR и/или рисковать приватностью.
10) Стоимость и SLO (экономика)
Storage: меньше байт → ниже $/TB-mo.
Compute: меньше IO → быстрее сканы; но декомпрессия тратит CPU.
Egress: меньше байт → ниже трафик/время копий.
SLO-компромисс: подберите кодек/уровень так, чтобы `p95_latency` остался в целевом окне.
yaml hot:
format: parquet codec: snappy target_p95_ms: 1000 max_scan_mb: 2048 warm:
format: parquet codec: zstd:4 target_p95_ms: 2500 compaction: daily cold:
format: parquet codec: zstd:7 glacier: true retention: 365d
11) Практики для движков (ClickHouse/Snowflake/BigQuery/Redshift/Presto)
ClickHouse: CODEC’и на колонках (LZ4/ZSTD/DoubleDelta), ORDER BY для RLE/сканов, TTL/компакшн.
Snowflake/BigQuery: автоматика форматов/кластеризации; помогайте cluster by (дата, tenant, ключи фильтра).
Redshift/Presto/Trino: Parquet/ORC с ZSTD, настройка `hive.exec.compress.output`, статистики и разделение файлов.
12) Пайплайны: где включать сжатие
Ingest: сжатые батчи (ZSTD/LZ4) при записи в lake.
Transform/DBT: создавайте колоночные цели с нужным кодеком и сортировкой.
Serve/OLAP: материализованные представления с подходящим кодеком; предагрегаты для горячих дашбордов.
Export: для CSV/JSON — gzip/zstd; лучше отдавать Parquet.
13) Тестирование и валидация
AB-профилирование: набор запросов → сравнить p50/p95, bytes scanned, CPU time, CR.
Golden-наборы: проверка корректности после перекодирования/компакшна.
Regression perf tests: алерты, если p95 ↑ > X% после смены кодека/уровня.
DQ-правила: типы/диапазоны/NULL-rate не должны меняться при перекладке.
14) Политики хранения и TTL
Tiered: hot (7–14 дн.), warm (30–90 дн.), cold (≥180 дн.).
Downsampling: по мере “охлаждения” храните агрегаты/эскизы вместо сырого.
Retention/Legal hold: не удаляйте коллизии с нормативами; храните каталоги и версии.
15) Антипаттерны
“Везде Gzip level 9”: дорогой CPU, выгоды нет.
Без сортировки/кластеризации: плохие RLE/zone-maps → сканы дорогие.
JSON как формат хранилища: удобно для ingest, плохо для аналитики.
Слишком мелкие файлы: раздувают метаданные/seek; CR падает.
Шифрование до сжатия: почти нулевой CR.
Lossy без маркировки: нарушение доверия и отчетности.
16) Дорожная карта внедрения
1. Discovery: профили запросов/данных, SLO и бюджеты.
2. MVP: Parquet + ZSTD/Snappy, базовая сортировка/кластеризация, компакшн.
3. Tuning: уровни ZSTD, размеры страниц, cluster by, bloom/zone-maps.
4. Warm/Cold: tiered storage, downsampling/эскизы, egress-политики.
5. Hardening: регрессионные перф-тесты, DQ, runbooks перекодирования.
17) Чек-лист перед релизом
- Формат: Parquet/ORC; включены статистики/словари.
- Кластеризация по ключам фильтрации; партиции по дате/тенанту.
- Кодеки: hot=Snappy/LZ4, warm/cold=ZSTD(3–7); p95 в норме.
- Компакшн настроен; нет small files; целевые размеры файлов/страниц.
- DQ и golden-наборы зеленые; типы/диапазоны сохранены.
- Шифрование после сжатия; PII маскированы; ретеншн/Legal-hold соблюдены.
- Перф-регрессии мониторятся; алерты по p95/bytes scanned/CR.
- Документация политики хранения и инструкций перекодирования готова.
18) Мини-шаблоны
DBT (таблица Parquet с ZSTD и кластеризацией):sql create table if not exists analytics.sales_daily cluster by (event_date, tenant_id)
as select from {{ ref('sales_daily_view') }};
-- в конфиге модели: materialized=table, file_format=parquet, compression=zstd
Политика компакшна (псевдо):
yaml compaction:
target_file_mb: 256 small_file_threshold_mb: 32 schedule: "hourly"
Конфиг downsampling (псевдо):
yaml timeseries:
raw: keep: 14d rollup_1m: keep: 90d rollup_1h: keep: 365d rollup_1d: keep: 1825d
Итог: сжатие аналитических данных — это не только “включить кодек”, а целостная стратегия: правильный формат, энкодинг колонок, сортировка и партиционирование, компакшн и уровни хранения, уважение к шифрованию и SLO. Грамотный дизайн дает быстрее сканы, ниже счета и предсказуемую производительность — без компромисса в доверии к данным.