DuckDB для аналитика: OLAP прямо в Python

Проверь себя · 1/3разбор после ответа
Для отчёта по регистрациям вам нужны только 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 duckdb
import 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.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

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-модели локально.

Недельный эксперимент даст понять, подходит ли.

Читайте также

FAQ

DuckDB бесплатный?

Да, лицензия MIT. Можно использовать в коммерческих проектах без ограничений.

Подходит ли для прода?

Для встраиваемых сценариев (локальный анализ, dbt-тесты) — да. Для многопользовательского веб-приложения — нет, нужна полноценная БД.

С JSON работает?

Да, поддерживает JSON-типы и функции, похоже на JSONB в PostgreSQL.

Можно ли из Rust/Go/Java?

Да, биндинги есть для всех популярных языков. В Python самый развитый API.