Проектирование Storage Layer
Второй deliverable — выбор форматов хранения для каждого слоя. Это ядро capstone-проекта: здесь сходятся знания из 14 модулей. Каждое решение должно быть привязано к workload и обосновано ссылкой на конкретный материал курса.
Архитектура из обзора проекта: три слоя (bronze → silver → gold), каждый с разным workload:
Bronze
Bronze layer workload: write-heavy, append-only. 10K events/sec steady → файлы каждые 30 сек. Никогда не обновляется. Основная операция: append. Чтение: редко (reprocessing, debugging). Schema evolution: частая (upstream DDL changes).Silver
Silver layer workload: merge-heavy. SCD Type 2, upserts, deduplication. Каждый batch: read existing + merge new → write updated. Balance между read и write performance. Schema стабильная (мы контролируем silver schema).Gold
Gold layer workload: read-heavy. Pre-aggregated materialized views. Обновление: раз в час или реже. Чтение: постоянное (BI, ML, ad-hoc). Оптимизация: scan speed, predicate pushdown, partition pruning.File Format: Parquet vs ORC
Первый выбор — columnar file format. Для нашего сценария два реалистичных кандидата: Parquet и ORC.
Bronze: File Format
Bronze: append-only, write throughput важен. Parquet: row group model позволяет streaming write (flush per row group). ORC: stripe model аналогичен. Разница: Parquet row groups чуть проще для append (нет ORC stripe footer с bloom filters). Но разница минимальна.Silver: File Format
Silver: merge-heavy. Для merge нужно: (1) быстрый lookup по PK (для matching existing rows), (2) эффективный write обновлённых файлов. Parquet: нет нативных bloom filters (добавлены в v2, но не все engines поддерживают). ORC: нативные bloom filters, row-level indexes.Gold: File Format
Gold: read-heavy analytics. Columnar scan speed — ключевая метрика. Parquet и ORC оба columnar, но: Parquet page-level statistics → column chunk pruning. ORC stripe-level statistics + bloom filters → более точный pruning при point queries.Мы выбираем Parquet для всех трёх слоёв. Это не “один формат на всё” — ошибка из обзора. Parquet — единый file format, но encoding, compression, row group size, sort order различаются по слоям. Дифференциация — на уровне настроек, а не формата.
Table Format: Delta Lake vs Iceberg vs Hudi
Table format — это метаданные и ACID поверх файлов. Три кандидата: Delta Lake, Iceberg, Hudi.
Delta Lake
Delta Lake: log-based transaction protocol. Commit log в _delta_log/. Checkpoint каждые 10 коммитов. ACID через optimistic concurrency. Tight integration с Spark (от Databricks). Open-source + managed (Databricks).Apache Iceberg
Apache Iceberg: tree-based metadata. Manifest list → manifest files → data files. Snapshot isolation. Engine-agnostic by design. Open governance (Apache Foundation). Adopted by Netflix, Apple, AWS.Apache Hudi
Apache Hudi: record-level index для fast upsert. MoR (Merge-on-Read) — default. Log files для real-time updates. Optimized для streaming ingestion + CDC. Uber-originated.Рекомендация: Iceberg
Решение: Apache Iceberg
Apache Iceberg — рекомендация для capstone-платформы. Engine-agnostic design позволяет использовать Spark для ETL, Trino для ad-hoc, DuckDB для local analytics — без vendor lock. Partition evolution — critical для evolving data platform.Hudi мог бы быть лучшим выбором если бы наш primary workload был high-frequency upsert (тысячи upserts/sec на одной таблице). Record-level index Hudi оптимизирован именно для этого. Но наш silver layer — batch merge раз в 30 сек, что Iceberg обрабатывает достаточно эффективно. См. Hudi index types для details.
Encoding Strategy per Layer
Encoding — как значения закодированы внутри column chunks. Выбор зависит от типа данных и access pattern:
Bronze: Default
Bronze encoding: default Parquet encoding. Spark writer автоматически выбирает: PLAIN для strings с высокой кардинальностью, DICTIONARY для low-cardinality, DELTA_BINARY_PACKED для integers. Не оптимизируем вручную — bronze write speed важнее.Silver: Targeted
Silver encoding: более аккуратное. Знаем schema, знаем кардинальность. Словарные кодировки для status, region, category. Delta encoding для timestamps. RLE для sorted columns.Gold: Optimized
Gold encoding: максимальная оптимизация для read. Pre-aggregated данные: много integers (counts, sums), low-cardinality dimensions. Dictionary + RLE on sorted columns = максимальная compression + scan speed.Подробный разбор каждого encoding — в Модуле 08. Здесь мы применяем эти знания к конкретным колонкам нашей платформы. Ключевое правило: encoding выбирается по кардинальности и типу данных, а не по слою.
Compression Strategy per Layer
Compression — последний уровень оптимизации. Trade-off: compression ratio vs CPU overhead:
Bronze: Snappy
Bronze: balance между write speed и storage cost. Snappy: быстрый (fast compress + decompress), moderate ratio (~2-3x). Zstd: лучше ratio (~4-5x), но медленнее compress. Для streaming ingestion — Snappy safe default.Silver: Zstd (level 3)
Silver: balance. Merge операции = read + write. Zstd level 3 — золотая середина: лучше ratio чем Snappy при сопоставимой decompress speed. Compress медленнее, но silver write = batch (не streaming).Gold: Zstd (level 6)
Gold: read-optimized. Zstd level 6+: максимальная compression ratio, decompress всё ещё быстрый (~1000 MB/s). Gold обновляется редко (раз в час) — compress speed не важна. Меньше данных = быстрее scan = лучше BI response time.Подробный разбор trade-offs Snappy vs Zstd vs LZ4 — в Модуле 09, Урок 02. Для capstone: Snappy для write-heavy, Zstd с возрастающим level для read-heavy — стандартный паттерн в production data platforms.
Partitioning и Sort Order
Partitioning определяет directory layout. Sort order определяет порядок строк внутри файлов. Оба влияют на query performance:
Bronze: ingestion_date
Bronze partitioning: по ingestion_date. Простая, предсказуемая. Каждый день — отдельная партиция. ~500 GB/день → manageable size. Partition pruning: queries по дате отсекают 99%+ данных.Silver: order_date, region
Silver partitioning: по order_date + region (для orders таблицы). Двойная партиция: аналитики фильтруют по date (всегда) и часто по region. Iceberg partition evolution позволяет добавить region позже без rewrite.Gold: report_date
Gold partitioning: по report_date. Одна партиция = один batch rebuild. Sort order: по primary dimension (region, category). Z-ordering для multi-dimensional queries если engine поддерживает (Iceberg v2 sort order).CoW vs MoR для Silver Layer
Ключевое решение для silver layer: Copy-on-Write vs Merge-on-Read:
Copy-on-Write (CoW)
Copy-on-Write: каждый merge перезаписывает весь affected file. Новая версия файла содержит merged результат. Старая версия — garbage collected. Read: всегда быстрый (файлы уже merged). Write: медленный (full file rewrite).Merge-on-Read (MoR)
Merge-on-Read: write записывает delta files (только изменения). Read: merge на лету (base + deltas). Периодическая compaction объединяет deltas в base. Write: быстрый. Read: медленнее (merge overhead). Complexity: выше.Рекомендация: CoW для silver layer:
- Merge batch: ~300K events / 30 sec — CoW file rewrite manageable
- Downstream reads (gold rebuild, analytics) — всегда быстрые
- Operational simplicity — нет compaction jobs
- Iceberg CoW merge:
MERGE INTO silver USING staging ON silver.id = staging.id ...
Если бы наш merge был high-frequency (continuous per-record, а не micro-batch), MoR был бы обязателен. Hudi MoR с record-level index — оптимальный для этого сценария. Но наш batch merge каждые 30 сек — CoW territory. Подробнее: CoW vs MoR, Hudi MoR.
Row Group и Target File Size
Последний уровень настроек — физический размер файлов и row groups:
Сводка решений
Упражнение: ваш Storage Layer Design
Ваша задача — описать storage layer для capstone-платформы. Наши рекомендации выше — один из возможных вариантов. Вы можете согласиться, модифицировать, или предложить полностью другую архитектуру. Ключ — обоснование:
Обоснование — не формальность. “Parquet because it’s popular” — не обоснование. “Parquet для bronze потому что: (1) Iceberg нативно работает с Parquet (Модуль 12), (2) Spark Structured Streaming write path оптимизирован для Parquet, (3) streaming append не использует ORC advantages (bloom filters, indexes)” — обоснование.
В следующем уроке вы проверите свои решения на практике: запустите Docker lab, соберёте бенчмарки, и сравните результаты с ожиданиями.