Data engineering
Parquet: собери эффективную для запросов таблицу озера
Читать про pushdown и small-files problem — не то же самое, что сделать запрос дешевле в 50 раз. Возьми реальный датасет, разложи его в Parquet так, как разложил бы сеньор, и докажи — числами прочитанных байтов, а не размахиванием руками, — что именно раскладка делает работу.
Преврати ментальную модель юнита в воспроизводимый цикл: конвертируй в Parquet, кластеризуй и задавай размер под запросы, которые реально гоняешь, проталкивай фильтры и проекции в читатель, и проверь выигрыш числами до/после по прочитанным байтам и времени на идентичных запросах.
Возьми широкий многомиллионный CSV-датасет и преврати его в эффективную для запросов Parquet-таблицу, чьи фильтрованные запросы с проекцией читают малую долю байтов, которые прочитал бы полный скан CSV — доказывая каждое решение по раскладке измеренными прочитанными байтами, а не оценками.
- Таблица до/после по CSV, наивному Parquet и тюнингованному Parquet: прочитанные байты, размер на диске и время запроса для идентичного фильтрованного запроса с проекцией.
- Доказательство, что тюнингованная раскладка действительно пропускает row groups — статистика движка по запросу или число прочитанных row groups против общего — и что несортированная версия пропускает мало или ничего.
- Сравнение кодеков (snappy против zstd) с измеренным размером на диске и временем чтения и однострочной рекомендацией для горячих против холодных данных.
- Демонстрация small-files: время планирования/листинга на раскладке из крошечных файлов против скомпактированной, показывающее выигрыш от compaction.
- Абзац-описание, называющий для каждого выигрыша, какой механизм его дал — column pruning, row-group skipping, encoding или compaction — чтобы числа отображались на причины.
- Добавь page-level статистики и Bloom filter на колонку равенства высокой кардинальности и покажи дополнительный пропуск (или что он не помог и почему).
- Положи тюнингованный Parquet под table format (Iceberg или Delta Lake) и продемонстрируй одну возможность, которой сырые файлы дать не могут: атомарную schema evolution (добавь/переименуй колонку) или time travel к прошлому снапшоту.
- Добавь CI-проверку, которая падает, если запрос читает больше пороговой доли общих байтов, чтобы регрессия в кластеризации или проекции ловилась автоматически.
- Повтори фильтрованный запрос во втором движке (например DuckDB и Spark) и покажи, что та же раскладка Parquet даёт пропуск согласованно между движками.
Это цикл, который ты гоняешь всякий раз, когда таблица озера медленная: конвертируй в Parquet, затем заставь раскладку делать работу — кластеризуй по колонкам фильтра, чтобы диапазоны min/max были пропускаемы, задавай размер row group в байтах, проталкивай предикат и список колонок в читатель, выбирай кодек по горячее-против-холодного и никогда не dictionary-кодируй почти уникальную колонку. Затем докажи это прочитанными байтами и пропущенными row groups на идентичных запросах и почини small-files problem через compaction. Сделав это однажды на реальном датасете, ты превращаешь механику формата в инстинкт.