Прямой ответ
DuckDB — встраиваемая аналитическая СУБД («SQLite для аналитики»): SQL-запросы выполняются прямо в процессе Python, по файлам (parquet/CSV/JSON — без загрузки в «базу»), колоночным движком с векторизацией, и с данными больше оперативной памяти (out-of-core на диск). Для аналитического пайплайна это означает: тяжёлые фильтрации/джойны/агрегации уходят из pandas-кода в SQL одной строкой (duckdb.sql("SELECT ... FROM 'data/*.parquet'")), обмен с pandas — почти бесплатный (общий Arrow-формат), а «файл не влезает в память» перестаёт быть причиной поднимать сервер БД. Граница честности: DuckDB — аналитика (OLAP), не замена транзакционной БД приложения (OLTP — PostgreSQL).
Модель: SQL поверх файлов
Ключевая идея — файл как таблица: SELECT city, avg(price) FROM 'sales/*.parquet' WHERE year = 2026 GROUP BY city работает без импорта, CREATE TABLE и подключения — glob по директории читает все части, схема выводится из файлов (parquet — надёжно; CSV — с оговорками на типы, о форматах — статья про CSV/parquet). Из Python: import duckdb; duckdb.sql("...").df() (результат в pandas) или .arrow(), .fetchall(); переменные pandas участвуют в запросах по имени (duckdb.sql("SELECT * FROM df WHERE x > 0") — подставляется DataFrame из области видимости). Persistent-база (duckdb.connect("my.duckdb")) нужна для кеша/промежуточных таблиц; «одноразовый» анализ работает in-memory без файла.
Почему быстрее pandas на тяжёлом
Три механики: колоночное исполнение (агрегация по двум колонкам из ста не читает остальные — как в parquet, так и в исполнении); векторизованный движок (операции над батчами значений, а не построчный Python — те же принципы, что в статье про векторизацию pandas, но в движке запросов с планировщиком); out-of-core (данные больше RAM обрабатываются с сбросом на диск — pandas в той же ситуации уходит в swap и умирает). Практический эффект: джойн двух файлов по миллиону строк или GROUP BY по десяткам миллионов записей — секунды на ноутбуке, без кластеров и клауд-сервисов. Многопоточность движка используется автоматически.
Сценарии из практики
Быстрый осмотр выгрузки: SELECT * FROM 'export.csv' LIMIT 10 + DESCRIBE SELECT * FROM 'export.csv' (типы, которые вывел DuckDB) — быстрее pandas-разведки на больших файлах. Фильтр перед pandas: тяжёлый WHERE/GROUP BY в SQL, в pandas — только маленький результат (паттерн «DuckDB готовит, pandas полирует»). Джойны больших файлов: вместо merge по памяти — SQL-join поверх файлов. Консолидация: COPY (SELECT * FROM 'data/*.parquet') TO 'all.parquet' — склейка партиций одной командой; read_csv_auto с unify-схемой для разнородных CSV. Замена «SQLite для аналитики»: там, где SQLite упирается в построчное исполнение, DuckDB летает; но для транзакционного хранения приложения — по-прежнему PostgreSQL (настройка — в статье про локальный PostgreSQL).
Интеграция с pandas и экосистемой
Обмен через Arrow — near zero-copy: duckdb.sql(q).df() и регистрация pandas-объектов (duckdb.register("t", df)) не копируют данные лишний раз; polars/arrow-таблицы — так же. Jupyter-интеграция — расширение %load_ext sql/duckdb-магия для SQL-ячеек; CLI (duckdb в терминале) — для ad-hoc без Python. Полезные расширения экосистемы: httpfs (запросы прямо по HTTPS/S3-файлам), spatial, excel-сканер. Репортаж-паттерн: SQL-запросы лежат в .sql-файлах рядом с кодом (ревью-верифицируемы и переиспользуемы), Python отвечает за оркестрацию и вывод.
Границы и грабли
DuckDB не для: высококонкурентной OLTP-нагрузки (модель — один писатель; веб-приложение с тысячами транзакций — это PostgreSQL), замены БД приложения, сценариев «много мелких точечных записей». Грабли практики: вывод типов CSV может удивить (явные columns=/types= при нестабильных выгрузках); SELECT * по десяткам колонок на больших данных — всё равно медленно (колоночность работает только при явном выборе колонок); память на большие джойны/агрегации без GROUP BY (DISTINCT/ORDER BY по сотням миллионов) — планируйте out-of-core-путь (temp_directory); версионирование формата базы (файл .duckdb привязан к версии движка — для обмена используйте parquet, не файл базы).
Практический сценарий: ночная выгрузка в утренний отчёт
Характерный пайплайн: ночью выгрузка из PostgreSQL складывается в директорию parquet-партиций по дням; утром аналитик собирает отчёт. На pandas это читалось бы целиком в память и фильтровалось в процессе; на DuckDB тяжёлая часть уходит в один SQL-запрос по glob'у: выборка нужного периода (предикат-пушдаун отсечёт партиции и строковые группы до чтения), джойн со справочником и группировка — движок выполняет всё колоночно и в несколько потоков, а в pandas через .df() приезжает только итоговая табличка на пару тысяч строк, с которой уже удобно работать и строить графики. Весь промежуточный объём — десятки гигабайт — в память не попадает вовсе. Если отчёт регулярный, запрос кладётся в .sql-файл рядом с пайплайном (ревьюится, версионируется, переиспользуется), а Python-скрипт занимается только оркестрацией: проверить свежесть партиций, выполнить SQL, положить результат в xlsx для рассылки. Когда в отчёт добавляется новый срез — правится SQL, а не ползучий pandas-код с промежуточными датафреймами. Для разовых разведок тот же запрос гоняется в CLI или Jupyter-ячейке; разница с «поднять PostgreSQL и залить туда файлы» — в том, что поднимать и заливать ничего не нужно: файлы уже являются базой.
FAQ
DuckDB или PostgreSQL для аналитики? Не конкуренты: PostgreSQL — транзакционное хранилище приложения (и аналитика умеренных объёмов), DuckDB — аналитический движок поверх файлов и выгрузок. Частая связка: приложение пишет в PostgreSQL, выгрузка в parquet, аналитика в DuckDB.
DuckDB или Polars? Polars — DataFrame-библиотека (код на Python), DuckDB — SQL-движок; производительность сопоставима, выбор — про язык запросов и экосистему. Они дружат (обмен через Arrow), и «Polars для трансформаций + DuckDB для тяжёлых SQL» — нормальная комбинация.
Правда ли, что работает с данными больше памяти? Да: out-of-core исполнение сбрасывает промежуточные данные на диск (медленнее in-memory, но работает там, где pandas ушёл бы в swap). Предел — диск, не RAM.
Нужна ли DuckDB серверная установка?
Нет: pip install duckdb — и движок встроен в процесс. CLI-бинарь опционален для ad-hoc. Никаких демонов, портов и администрирования — в этом половина привлекательности.
Источники: документация DuckDB (docs, Python API, работа с файлами) — ссылки в шапке.