awesome-everything EN
↑ Обратно к восхождению

Data engineering

Parquet: чтение кода и конфигов

Суть Читай реальные пути чтения PyArrow/DuckDB и конфиг писателя, предсказывай I/O и объём прочитанных байтов, выбирай решение с наибольшим рычагом для pushdown, размера и проекции.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

Проблемы Parquet диагностируются в пути чтения и в конфиге писателя, а не в документации. Читай каждый сниппет, предскажи, сколько байтов движок реально трогает, и выбери решение, которое сеньор делает первым.

Цель

Отработай цикл, который ты запускаешь на каждом медленном запросе к озеру: увидь, где применяются фильтр и проекция, реши, разложил ли писатель данные так, чтобы их можно было пропускать, и тянись к решению по раскладке раньше, чем к железу.

Сниппет 1 — pushdown потерян внутри движка

import pyarrow.parquet as pq

# events/ — год дневных Parquet-файлов, отсортированных по `day`
table = pq.read_table("s3://lake/events/")      # читает всё
df = table.to_pandas()
df = df[df["day"] == "2024-02-01"]               # фильтр после чтения
result = df[["user_id", "country"]]              # проекция после чтения
Викторина

Это читает ~1.9 ГБ и медленно, хотя данные отсортированы по day. Почему и какое решение даёт наибольший рычаг?

Сниппет 2 — конфиг писателя

import pyarrow.parquet as pq

# одна батч-запись ~50 ГБ, запросы почти всегда по `country`
pq.write_table(
    table,
    "s3://lake/events_2024.parquet",
    row_group_size=2048,        # строк на row group
    compression="snappy",
    write_statistics=True,
)
Викторина

Для батч-записи 50 ГБ эта раскладка сделает фильтрованные запросы медленными, несмотря на write_statistics=True. Что не так и каково решение?

Сниппет 3 — проекция колонок против SELECT *

-- DuckDB над широкой Parquet-таблицей на 120 колонок в S3
SELECT *
FROM read_parquet('s3://lake/wide_events/*.parquet')
WHERE country = 'DE';
Викторина

Аналитику нужны только user_id и amount, но он запускает SELECT * на таблице из 120 колонок. Какова цена и каково решение?

Сниппет 4 — откат словаря

# колонка session_id высокой кардинальности, ~10М почти уникальных UUID
pq.write_table(
    table,                       # содержит колонку `session_id` из UUID
    "s3://lake/sessions.parquet",
    use_dictionary=True,         # включено по умолчанию
    compression="zstd",
)
Викторина

Колонка session_id выходит едва меньше plain-байтов, а CPU записи высокий. Что произошло?

Итог

Каждый медленный запрос к Parquet читается в пути доступа и конфиге писателя: протолкни предикат и список колонок в читатель, иначе ни row-group skipping, ни column pruning не сработают; задавай размер row group в байтах, целясь в ~128 МБ-1 ГБ, и кластеризуй по колонке фильтра, чтобы её диапазоны были пропускаемы; SELECT * тихо читает каждый column chunk, так что всегда проецируй; а dictionary encoding на колонке высокой кардинальности переполняется и откатывается на plain, стоя CPU без выигрыша по размеру. Диагностируй по тому, где приземляются фильтр и проекция, чини раскладку, затем заново измеряй прочитанные байты.

Продолжить восхождение ↑Parquet: собери эффективную для запросов таблицу озера
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.