DuckDB для аналитика: OLAP прямо в Python
Что такое DuckDB
DuckDB — это встраиваемая аналитическая БД. Можно представить её как SQLite для аналитики. Не нужен сервер, не нужно настраивать кластер — поставили пакет, импортировали в Python, написали SQL-запрос. База живёт прямо в процессе приложения.
Под капотом DuckDB — колоночное хранение (как ClickHouse), vectorized execution, современный оптимизатор запросов. По скорости на аналитических задачах она сопоставима с serverless ClickHouse, но запускается за миллисекунды и не требует ничего, кроме pip install duckdb.
Для аналитика это идеальный инструмент для локальной работы с большими файлами. Нужно прогонять SQL по parquet на 5 GB — DuckDB справится на ноутбуке, pandas в такой объём не влезет.
Установка и первый запрос
pip install duckdbimport duckdb
# Прямой запрос без создания файла-БД
result = duckdb.sql("SELECT 42 AS answer")
result.show()DuckDB умеет работать в режиме in-memory (данные живут в RAM, не сохраняются) или с persistent файлом:
# Persistent
con = duckdb.connect('analytics.duckdb')
con.execute("CREATE TABLE orders (id INT, amount NUMERIC)")
con.execute("INSERT INTO orders VALUES (1, 100), (2, 200)")
con.close()
# In-memory (default)
con = duckdb.connect(':memory:')Работа с CSV
Одна из killer-фич DuckDB — читать файлы напрямую из SQL, без импорта:
duckdb.sql("""
SELECT
category,
SUM(amount) AS revenue,
COUNT(*) AS orders
FROM 'orders.csv'
WHERE status = 'paid'
GROUP BY category
ORDER BY revenue DESC
""").show()Прямо в FROM указан путь к файлу. DuckDB сам парсит CSV, определяет типы, выполняет запрос. Работает с gzip-сжатием, может читать несколько файлов по wildcard:
duckdb.sql("SELECT * FROM 'logs/*.csv'")Parquet — главная сила
Parquet — колоночный формат, идеально подходит DuckDB. Запросы на parquet в несколько раз быстрее CSV и эффективнее по памяти:
# Чтение 10 GB parquet за секунды
duckdb.sql("""
SELECT date, SUM(amount)
FROM 'year_data/*.parquet'
WHERE date >= '2026-01-01'
GROUP BY date
""").show()DuckDB использует partition pruning (читает только нужные файлы) и projection pushdown (читает только нужные колонки). Для data lake pattern это критично.
Интеграция с pandas
DuckDB может напрямую запрашивать pandas DataFrames:
import pandas as pd
import duckdb
orders = pd.read_csv('orders.csv')
products = pd.read_csv('products.csv')
# SQL прямо на pandas dataframes
result = duckdb.sql("""
SELECT
p.category,
SUM(o.amount) AS revenue
FROM orders o
JOIN products p ON p.product_id = o.product_id
GROUP BY p.category
""").to_df()Это меняет подход к pandas-работе. Сложные JOIN-ы и GROUP BY писать в SQL проще и быстрее, чем через методы pandas. А конвертации между типами данных бесплатны — DuckDB и pandas используют Apache Arrow под капотом.
Разобраться с современным Python-стеком — важная часть middle+ подготовки. В тренажёре Карьерник есть задачи на SQL и Python для аналитики с разборами инструментов.
Типичные сценарии
Быстрый анализ большого файла
CSV или parquet на несколько GB. pandas падает по памяти, полноценную БД разворачивать не хочется. DuckDB — идеальное решение:
import duckdb
# Один раз прогнать тяжёлую агрегацию
summary = duckdb.sql("""
SELECT
DATE_TRUNC('day', event_time) AS day,
COUNT(DISTINCT user_id) AS dau,
COUNT(*) AS events
FROM 'huge_events.parquet'
WHERE event_time >= '2026-01-01'
GROUP BY 1
ORDER BY 1
""").to_df()Теперь summary — маленький DataFrame на 100 строк. Дальше работаете с ним как обычно.
ETL-скрипты
Вместо громоздких цепочек pandas-операций — чистый SQL:
duckdb.sql("""
COPY (
SELECT
user_id,
SUM(amount) AS total,
COUNT(*) AS orders,
MIN(created_at) AS first_order,
MAX(created_at) AS last_order
FROM 'raw_orders.parquet'
WHERE status = 'paid'
GROUP BY user_id
) TO 'user_summary.parquet' (FORMAT PARQUET)
""")Читаем raw, агрегируем, сохраняем в новый parquet. Одна команда, запускается за секунды на миллионах строк.
Присоединение внешних источников
DuckDB умеет запрашивать удалённые файлы — S3, HTTP, Google Cloud Storage:
duckdb.sql("""
SELECT COUNT(*)
FROM 's3://my-bucket/events/2026/*.parquet'
""")Для этого нужны credentials. DuckDB поддерживает httpfs-extension для работы с remote storage.
Удобный SQL на ноутбуке
Jupyter + DuckDB даёт удобный инструмент для ad-hoc анализа:
import duckdb
import pandas as pd
# Подключаемся к persistent базе
con = duckdb.connect('analytics.duckdb')
# Вопросы аналитика — на SQL, быстро
con.sql("""
WITH monthly AS (
SELECT DATE_TRUNC('month', created_at) AS month,
COUNT(*) AS orders
FROM orders GROUP BY 1
)
SELECT * FROM monthly ORDER BY month DESC
""").show()DuckDB vs SQLite
SQLite тоже встраиваемая БД, но для OLTP (единичные записи, транзакции). DuckDB для OLAP (аналитика, агрегаты). На аналитических задачах DuckDB в 10-100 раз быстрее SQLite.
Если ваша задача — хранить настройки приложения или небольшие связанные данные, SQLite. Если считать метрики по большому CSV — DuckDB.
DuckDB vs ClickHouse
ClickHouse — distributed, серверный, для production analytics с большими объёмами. DuckDB — локальный, embedded.
В какой-то мере это spectrum:
DuckDB — для разработки, ad-hoc, небольших dashboards. Запускается за миллисекунды.
ClickHouse — для production, множественных пользователей, объёмов в терабайты.
Они дополняют друг друга. Можно тестировать логику на DuckDB локально, потом переносить в ClickHouse для production.
dbt-duckdb
Интересно: для DuckDB есть dbt-адаптер. Это позволяет писать dbt-модели, выполняемые локально на DuckDB — идеально для тестирования моделей без production-среды.
pip install dbt-duckdbНастройка profile:
my_project:
target: local
outputs:
local:
type: duckdb
path: ./analytics.duckdbЛокальная среда для dbt development — удобно.
Ограничения
Не для multi-user production. DuckDB предполагает одного пользователя или процесса. Для real-time аналитики с тысячами запросов — ClickHouse или Snowflake.
Ограниченная поддержка UPDATE/DELETE. DuckDB оптимизирован для аналитических чтений. OLTP-операции работают, но не так эффективно.
Нет distributed вычислений. Один сервер, одна машина. Для петабайтов нужны специализированные решения.
Производительность
На 10 GB parquet-файле — пример бенчмарка (приблизительно):
SELECT COUNT(DISTINCT user_id)— 1.2 секунды.GROUP BY category SUM(amount)— 0.8 секунды.JOIN 10M × 1M— 2.5 секунды.
Для сравнения — pandas на том же датасете падает по памяти или работает минуты.
Когда стоит попробовать
Если в вашей работе:
Часто приходят parquet/csv файлы на гигабайты, которые нужно быстро анализировать.
Используете pandas, но встречаете лимиты по памяти.
Хочется SQL для ad-hoc анализа без запуска отдельной БД.
Нужен быстрый способ тестировать dbt-модели локально.
Один недельный эксперимент даст понять, подходит ли.
Читайте также
- Polars vs Pandas
- Что такое ClickHouse
- Как работать с большим датасетом в pandas
- Как настроить dbt-проект
FAQ
DuckDB бесплатный?
Да, MIT license. Можно использовать в коммерческих проектах без ограничений.
На production годится?
Для embedded сценариев (локальный анализ, dbt-тесты) — да. Для multi-user web app — нет, нужна полноценная БД.
С JSON работает?
Да, поддерживает JSON типы и функции, похоже на PostgreSQL JSONB.
Можно ли в Rust/Go/Java?
Да, биндинги есть для всех популярных языков. В Python самый развитый API.