DuckDB для аналитика: OLAP прямо в Python
user_id и signup_at из таблицы users. Какой запрос лучше соответствует задаче и не тянет лишние поля?Что такое DuckDB
DuckDB — это встраиваемая аналитическая БД. Можно представить её как SQLite для аналитики. Не нужен сервер, не нужно настраивать кластер — поставили пакет, импортировали в Python, написали SQL-запрос. База живёт прямо в процессе приложения.
Под капотом DuckDB — колоночное хранение (как в ClickHouse), векторизованное выполнение, современный оптимизатор запросов. По скорости на аналитических задачах она сопоставима с 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, не сохраняются) или с постоянным файлом на диске:
# На диске
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()
# В памяти (по умолчанию)
con = duckdb.connect(':memory:')Работа с CSV
Одна из главных фишек 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-сжатием, может читать несколько файлов по маске:
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 это критично.
Интеграция с 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)
""")Читаем сырые данные, агрегируем, сохраняем в новый parquet. Одна команда, запускается за секунды на миллионах строк.
Подключение внешних источников
DuckDB умеет запрашивать удалённые файлы — S3, HTTP, Google Cloud Storage:
duckdb.sql("""
SELECT COUNT(*)
FROM 's3://my-bucket/events/2026/*.parquet'
""")Для этого нужны креды. DuckDB поддерживает расширение httpfs для работы с удалённым хранилищем.
Удобный SQL в ноутбуке
Jupyter + DuckDB даёт удобный инструмент для разового анализа:
import duckdb
import pandas as pd
# Подключаемся к файловой базе
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 — распределённый, серверный, для продовой аналитики с большими объёмами. DuckDB — локальный, встраиваемый.
В каком-то смысле это спектр:
DuckDB — для разработки, разовых задач, небольших дашбордов. Запускается за миллисекунды.
ClickHouse — для прода, множества пользователей, объёмов в терабайты.
Они дополняют друг друга. Можно тестировать логику на DuckDB локально, потом переносить в ClickHouse для прода.
dbt-duckdb
Интересно: для DuckDB есть адаптер dbt. Он позволяет писать dbt-модели, которые выполняются локально на DuckDB — идеально для тестирования моделей без продовой среды.
pip install dbt-duckdbНастройка профиля:
my_project:
target: local
outputs:
local:
type: duckdb
path: ./analytics.duckdbЛокальная среда для разработки dbt — удобно.
Ограничения
Не для продовой многопользовательской нагрузки. DuckDB предполагает одного пользователя или процесса. Для real-time аналитики с тысячами запросов — ClickHouse или Snowflake.
Ограниченная поддержка UPDATE/DELETE. DuckDB оптимизирован для аналитических чтений. OLTP-операции работают, но не так эффективно.
Нет распределённых вычислений. Один сервер, одна машина. Для петабайтов нужны специализированные решения.
Производительность
На 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 для разового анализа без запуска отдельной БД.
Нужен быстрый способ тестировать dbt-модели локально.
Недельный эксперимент даст понять, подходит ли.
Читайте также
- Polars vs Pandas
- Что такое ClickHouse
- Как работать с большим датасетом в pandas
- Как настроить dbt-проект
FAQ
DuckDB бесплатный?
Да, лицензия MIT. Можно использовать в коммерческих проектах без ограничений.
Подходит ли для прода?
Для встраиваемых сценариев (локальный анализ, dbt-тесты) — да. Для многопользовательского веб-приложения — нет, нужна полноценная БД.
С JSON работает?
Да, поддерживает JSON-типы и функции, похоже на JSONB в PostgreSQL.
Можно ли из Rust/Go/Java?
Да, биндинги есть для всех популярных языков. В Python самый развитый API.