データサイエンス・分析

DuckDB入門2026|SQLだけで高速データ分析を始める全手順

読了時間: 約14分

数百万行のCSVをpandasで読み込んだらメモリ不足で落ちた。データ分析の現場で一度は経験する場面だろう。DuckDBはこの問題を根本から解消するインプロセス分析エンジンで、ファイルを「読み込む」のではなく直接SQLで問い合わせるという発想で動く。

2026年3月にリリースされたバージョン1.5ではVARIANT型やGEOMETRY型が追加され、分析基盤としての守備範囲がさらに広がった。pip一発でインストールでき、サーバーもDockerも不要。SQLを書ける人なら今日から使い始められる。

DuckDBとは - SQLで完結するインプロセス分析エンジン

DuckDBはオランダのCWI(国立数学情報科学研究所)で生まれたOLAP特化のデータベースエンジンだ。PostgreSQLやMySQLのようなサーバー型とは根本的に異なり、アプリケーションのプロセス内で直接動作する「組み込み型」のアーキテクチャを採る。SQLiteのOLAP版、という説明が最も近い。

DuckDBの特徴を一言で

「サーバー不要で、手元のCSV・ParquetにそのままSQL。pandasの10〜100倍速い列指向エンジン」

PostgreSQLとの最大の違いは4つある。

  • 列指向ストレージ: 行単位ではなく列単位でデータを処理する。集計クエリ(SUM、AVG、GROUP BY)が圧倒的に速い理由がここにある
  • ベクトル化実行: 1行ずつではなくデータを塊(ベクトル)で処理する。CPUキャッシュ効率が段違いに上がる
  • ゼロコピー連携: pandasのDataFrameやApache Arrowのデータを、メモリコピーなしで直接クエリできる
  • ディスクスピル: メモリに収まらないデータは自動的にディスクに退避する。メモリ不足で落ちるpandasとの決定的な差

ライセンスはMIT。商用利用も自由で、DuckDB Labs社が開発をリードしている。クラウド版のMotherDuckもあるが、ローカルだけで完結する点が最大の魅力だ。

インストールと初期セットアップ

Python(pip)

Python環境が最もユーザーが多い。venvを作ってpipで入れるだけだ。

python -m venv .venv
source .venv/bin/activate
pip install duckdb

バージョン確認。

import duckdb
print(duckdb.__version__)
# 1.5.1

CLI(コマンドライン)

macOSならHomebrew、WindowsならWingetで入る。

# macOS
brew install duckdb

# Windows
winget install DuckDB.cli

# バージョン確認
duckdb --version

DuckDB 1.5で刷新されたフレンドリーCLIは、テーブルの見やすいフォーマット出力やタブ補完に対応している。筆者も以前のCLIから移行したが、出力の視認性が別物になった。

Jupyter Notebook

Jupyterで使う場合は追加でmagicコマンド用の拡張を入れると便利だ。

pip install duckdb jupysql
# セル内でSQLを直接実行
%load_ext sql
%sql duckdb:///:memory:

基本操作 - CSV・Parquetを直接SQLで叩く

このセクションのコードはpd.read_csv()を一行も書かない。ファイルパスを直接FROM句に渡す。それだけで分析が始まる。

CSVファイルの分析

-- CSVを直接クエリ(ヘッダー自動検出)
SELECT
    department,
    COUNT(*) AS employee_count,
    ROUND(AVG(salary)) AS avg_salary
FROM 'employees.csv'
GROUP BY department
ORDER BY avg_salary DESC;

read_csv関数で細かいオプションを指定することもできる。

-- 文字コード・区切り文字を指定
SELECT * FROM read_csv('data.csv',
    delim = '\t',
    header = true,
    encoding = 'utf-8'
) LIMIT 10;

Parquetファイルの分析

実際にParquetファイルで検証すると、列指向同士のプロジェクションプッシュダウンの効果がはっきり出る。100列あるファイルから3列だけ取得すれば、I/Oは3%で済む計算になる。

-- Parquetのメタデータだけ確認
SELECT * FROM parquet_metadata('sales_2025.parquet');

-- 必要な列だけ集計
SELECT
    product_category,
    SUM(revenue) AS total_revenue
FROM 'sales_2025.parquet'
WHERE region = 'APAC'
GROUP BY product_category;

ワイルドカードで複数ファイルをまとめて分析

-- logs/フォルダ内の全CSVを1つのテーブルとして扱う
SELECT
    filename,
    COUNT(*) AS row_count
FROM 'logs/*.csv'
GROUP BY filename;

これだけの操作がインストール直後に動く。ETLツールもデータベースサーバーも不要。データを受け取った当日に分析を始められる。

Python連携 - pandasと自在に行き来する

pandasのDataFrameは、変数名をそのままFROM句に書ける。追加の変換もメモリコピーも発生しない。

pandasのDataFrameに直接SQLを投げる

import duckdb
import pandas as pd

# pandasでデータを持っている状態
df = pd.read_csv('customers.csv')

# DataFrameに直接SQL(変数名がそのままテーブル名)
result = duckdb.sql("""
    SELECT
        prefecture,
        COUNT(*) AS cnt,
        AVG(purchase_amount) AS avg_amount
    FROM df
    WHERE age >= 30
    GROUP BY prefecture
    HAVING cnt >= 10
    ORDER BY avg_amount DESC
""")

# 結果をDataFrameに戻す
result_df = result.df()
print(result_df.head())

変数名dfがそのままFROM句のテーブル名になる。この仕組みは「リレーションAPI」と呼ばれ、DuckDBの目玉機能の一つだ。

pandasでは遅い処理をDuckDBに逃がす

筆者も実務でよく使うパターンがある。前処理と集計をDuckDBに任せ、最後の可視化だけpandasに戻す流れだ。

import duckdb
import pandas as pd

# 重い集計はDuckDBで
aggregated = duckdb.sql("""
    SELECT
        date_trunc('month', order_date) AS month,
        product_category,
        SUM(amount) AS total,
        COUNT(DISTINCT customer_id) AS unique_customers
    FROM 'orders_*.parquet'
    GROUP BY ALL
    ORDER BY month, total DESC
""").df()

# 可視化はpandasのplotで
aggregated.pivot_table(
    index='month',
    columns='product_category',
    values='total'
).plot(kind='bar', stacked=True)

Polarsとの連携

Polarsユーザーも同様に連携できる。.pl()メソッドでPolarsのDataFrameとして受け取る。

import duckdb
import polars as pl

lf = pl.scan_parquet('large_data.parquet')

# PolarsのLazyFrameにSQLを発行
result = duckdb.sql("""
    SELECT category, SUM(value) AS total
    FROM lf
    GROUP BY category
""").pl()  # Polars DataFrameで返る

pandas・Polarsとの使い分け判断基準

MotherDuck社が公開している3300万行ベンチマークと、各ツールの公式ドキュメントから判断基準をまとめた。

比較項目 pandas Polars DuckDB
処理モデル 行指向・即時評価 列指向・遅延評価 列指向・SQL
1億行GROUP BY 100秒超 or OOM 約15秒 約10秒
メモリ効率 データの2-3倍必要 データの1-1.5倍 ディスクスピル対応
学習コスト 低(情報が豊富) 中(独自API) 低(SQL知識で可)
エコシステム 最大(scikit-learn等) 拡大中 拡張機能で対応
向いている場面 小〜中規模の探索的分析 大規模データパイプライン SQL主体の集計・レポート

MotherDuck社のベンチマークを調べてみると、意外な結果が出ている。3300万行のデータセットでDuckDBが最速、Polarsが僅差で続き、pandasはメモリ不足で完走できなかった。Polarsが全局面で速いわけではない。

実務での使い分け

  • 数万行以下: pandasで十分。わざわざ乗り換える必要はない
  • 数十万〜数百万行 + SQLが得意: DuckDBの出番
  • 数百万行 + Pythonの書き味重視: Polarsが最適
  • 数千万行以上: DuckDB一択。メモリ制限を超えられるのはDuckDBだけ

なお、これら3つは排他的ではない。DuckDBでフィルタ・集計してからpandasに渡す「ハイブリッド運用」が、現場のエンジニアに聞くと最も多い使い方だという。

実務で効くDuckDBの活用パターン

パターン1: ログ分析(数GB級のCSV)

アクセスログやアプリケーションログの分析は、DuckDBの典型的なユースケースだ。数GBのCSVをDB不要でその場で分析できる。

-- 直近7日間のエラーログを集計
SELECT
    date_trunc('hour', timestamp) AS hour,
    error_code,
    COUNT(*) AS occurrences
FROM 'app_logs_2026_*.csv'
WHERE timestamp >= current_date - INTERVAL 7 DAY
  AND level = 'ERROR'
GROUP BY ALL
ORDER BY hour DESC, occurrences DESC;

パターン2: 複数データソースのJOIN

CSVとParquetを混在させたJOINも可能だ。実務でよくあるのが「CSVの顧客マスタとParquetの売上データの突き合わせ」で、ETLを組まず手元で完結する。

-- CSVの顧客マスタとParquetの売上データをJOIN
SELECT
    c.customer_name,
    c.segment,
    SUM(s.amount) AS total_purchases
FROM 'customers.csv' c
JOIN 'sales_2026.parquet' s ON c.id = s.customer_id
GROUP BY c.customer_name, c.segment
ORDER BY total_purchases DESC
LIMIT 20;

パターン3: Excelからの脱却

Excelで限界を感じている非エンジニアにもDuckDBは使える。CLIから直接CSVにSQLを投げるだけで、VLOOKUPやピボットテーブルと同等の処理が瞬時に終わる。

# CLIからワンライナーで集計
duckdb -c "SELECT region, SUM(sales) FROM 'monthly_report.csv' GROUP BY region"

パターン4: データ品質チェック

-- NULLや重複をチェック
SELECT
    COUNT(*) AS total_rows,
    COUNT(*) - COUNT(email) AS null_emails,
    COUNT(*) - COUNT(DISTINCT id) AS duplicate_ids,
    MIN(created_at) AS earliest,
    MAX(created_at) AS latest
FROM 'users.csv';

データを受け取ったらこのクエリを最初に走らせる。NULLの件数と重複IDの数が一画面に収まる。後工程で「なぜかJOINが合わない」という手戻りを防げる。

DuckDB 1.5の注目新機能

2026年3月にリリースされたDuckDB 1.5は、分析エンジンとしての進化が顕著なバージョンだ。実務に直結する機能を3つ取り上げる。

VARIANT型: スキーマレスデータの効率的な格納

Snowflakeの同名機能にインスパイアされた型で、JSON型とは異なりバイナリで型情報を保持する。半構造化データ(APIレスポンス、ログ等)を扱う場合、JSON型比で圧縮率・クエリ性能ともに向上する。

-- VARIANT型の利用例
CREATE TABLE events (
    id INTEGER,
    payload VARIANT
);

INSERT INTO events VALUES
    (1, {name: 'click', x: 100, y: 200}),
    (2, {name: 'scroll', offset: 500});

SELECT id, payload.name FROM events;

GEOMETRY型のコア統合

以前はspatial拡張が必要だったGEOMETRY型が、コアに組み込まれた。同一型・同一次元のジオメトリは「シュレッディング」により構造体に分解され、ディスク上のサイズが約3分の1に圧縮される。地理データ分析が身近になった。

フレンドリーCLI

CLIが全面刷新され、テーブル形式の見やすい出力、タブ補完、シンタックスハイライトに対応した。ターミナルで分析を完結させたい人にとっては、この改善だけでもアップデートする価値がある。

よくある質問

DuckDBは無料で商用利用できる?

MITライセンスなので、個人・商用問わず無料で利用できる。

pandasから乗り換える必要がある?

乗り換えではなく併用が現実的だ。pandasで読み込んだDataFrameにDuckDBでSQLを投げられるので、重い集計だけDuckDBに任せる使い方が最も効率がよい。既存のpandasコードを捨てる必要はない。

DuckDBはWebアプリの本番DBとして使える?

OLTP(トランザクション処理)には向かない。同時書き込みは単一プロセスに制限されるため、Webアプリのバックエンドには従来どおりPostgreSQLやMySQLを使うべきだ。DuckDBの領域はあくまで分析・集計処理。

MotherDuckとは何が違う?

MotherDuckはDuckDB Labs公認のクラウドサービスで、DuckDBエンジンをマネージド環境で提供する。チームでの共有やスケジューリングが必要な場合の選択肢だが、個人の分析作業ならローカルのDuckDBで十分だ。

どのくらいのデータ量まで扱える?

ディスクスピル機能があるため、メモリ以上のデータでも処理可能だ。実測では16GBメモリのマシンで100GB超のParquetファイルを問題なく集計できたという報告がある。ただし処理速度はメモリに収まる場合に比べて低下する。

まとめ

DuckDBは「SQLが書ける人のための、最も手軽な大規模データ分析ツール」という位置づけだ。サーバー不要、pip一発、ファイルに直接SQL。この手軽さで1億行の集計を10秒で終えられるのは、2026年時点でDuckDB以外に見当たらない。

pandasやPolarsと併用できるので、既存コードを捨てずに導入できる。手元のCSVでduckdb -c "SELECT COUNT(*) FROM 'data.csv'"を走らせてみると、0.x秒で返ってくる数字が、これまでpandasに使っていた時間を物語る。

DuckDBを深く学ぶための書籍