Стиснення аналітичних даних
1) Навіщо стискати аналітичні дані
Стиснення зменшує обсяг зберігання і трафік, прискорює скани за рахунок меншого IO і кращої кешованості. Ціна - CPU і (іноді) складність оновлень. Мета - оптимум «IO↔CPU↔tochnost↔stoimost» під ваші 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. Грамотний дизайн дає швидше скани, нижче рахунку і передбачувану продуктивність - без компромісу в довірі до даних.