← На главную

DuckDB читает данные Python в обход сети

16.06.2026 11:07 · hackernews

DuckDB прошёл путь от исследовательского проекта в CWI Amsterdam до одной из самых популярных баз данных десятилетия. Его используют везде: в ноутбуках, ETL-пайплайнах, дашбордах, CI-тестах, встроенной аналитике в SaaS и даже на iPhone с TPC-H. Вокруг него строят продукты: MotherDuck делает облачное хранилище, Hex и Omni используют как движок внутри приложений, Fivetran применяет для слияния данных, а Greybeam гоняет через него миллионы запросов.

DuckDB — это in-process аналитическая SQL-база. Аналитическая — значит оптимизирована под запросы, которые сканируют миллионы строк. In-process — нет сервера, вы подключаете библиотеку как NumPy или Polars. Ставится одной командой (pip install duckdb), весит меньше 20 мегабайт. Открывает папку с Parquet или CSV как готовую базу.

Главная фишка — скорость. DuckDB живёт в том же процессе, что и клиент. Это обходит главное узкое место классических баз: сериализацию и передачу данных по сети. В 2017 году авторы проекта Марк Раасвельдт и Ханнес Мюлесейн опубликовали статью «Don't Hold My Data Hostage», где показали, что ODBC и JDBC часто работают дольше самого запроса. Каждое значение кодируется, передаётся, декодируется — сотни миллионов вызовов функций. DuckDB этого избегает.

При работе с pandas DuckDB может использовать replacement scan и читать данные напрямую из памяти Python — zero-copy. С Arrow всё ещё чище, потому что Arrow — это уже колоночный формат для обмена данными.

Когда SQL попадает в DuckDB, начинается цепочка: парсинг в AST (используется форк парсера Postgres), привязка к схеме, оптимизация (~33 прохода), генерация физического плана. Оптимизатор двигает фильтры ближе к сканированию, переписывает подзапросы в джойны, использует dynamic programming для выбора порядка соединения таблиц.

Физический план разбивается на пайплайны — как конвейер. Простые операции (WHERE, проекция) работают сразу. Тяжёлые (ORDER BY, GROUP BY) — это pipeline breakers, они копят данные, а потом отдают. Каждый пайплайн параллелится: потоки получают свои куски данных и пишут в локальное состояние, потом всё сливается.

Хранилище — один файл .duckdb, как SQLite. Данные разбиты на блоки по 256 КБ с checksum. Колоночное хранение: читаются только нужные колонки. Роу-группы до 122 880 строк, у каждой — zone map с min/max. Если в WHERE указана дата, DuckDB сначала смотрит zone map и пропускает целые группы, если они не подходят.

С Parquet та же история: DuckDB читает только footer со статистикой, выбирает нужные row group и колонки, качает только их, даже с удалённого файла. CSV сложнее — там работает sniffer: определяет разделитель, типы колонок, заголовки на выборке из 20 480 строк.

В итоге до выполнения запроса движок делает кучу работы: парсит, привязывает, оптимизирует, строит план. Всё это — подготовка к Part 2, про само выполнение.

Читать оригинал →