DuckDB(ダックディービー)は、サーバーを立てずにアプリケーションのプロセスの中で動く、分析(OLAP)用の列指向SQLデータベースです。CSVやParquetのファイルを取り込まずにそのままSQLで集計でき、PythonやR、Java、Node.jsなどのクライアントAPIから利用できます。オランダの国立研究所CWIで生まれ、MITライセンスで公開されています。
この記事では、DuckDBの仕組みと版の状況(2026年9月28日公開の1.5.6、LTSの1.4、2026年10月予定の2.0)を整理したうえで、500万行のデータでSQLiteと集計・1行検索・ファイルサイズを比べた実測値、pandasのDataFrameをそのままSQLで集計したときの速さ、複数プロセスから書き込もうとしたときに実際に出るエラーを示します。インストールやファイル読み込みの手順はDuckDBの使い方で扱っています。
まとめ:DuckDBの要点
- DuckDBはプロセス内(in-process)で動く列指向の分析用SQLデータベースです。データベースは1ファイル(またはメモリ上)で、サーバーの起動や接続設定は要りません。
- 最新版は1.5.6(2026年9月28日)です。公式カレンダーのサポート終了日は、1.5系が2027年3月1日、長期サポート(LTS)版の1.4系が2026年11月17日です。Python 3.9では1.5系が入らず1.4.5が入ります。2.0.0は2026年10月21日の予定です(暫定)。
- 500万行の集計では、DuckDBがSQLiteより45〜388倍、pandasより約7倍速く終わりました(pandasとの比較は同じDataFrameをDuckDBのSQLで集計したもの)。一方、idで1行を取り出す処理は、インデックスを作ったSQLiteの方が約70倍速く終わりました(DuckDB側はインデックスなし)。
- 通常のインプロセス利用では、1つのデータベースファイルを読み書きモードで開けるのは1プロセスだけで、その接続中は別プロセスから読み取り専用でも開けません。すべての接続が読み取り専用なら、複数プロセスから同時に開けます。複数の利用者で書き込むならDuckLake(PostgreSQLをカタログにする形式)か、ベータ版のQuackを使います。
- Python・Java(JDBC)・Node.js・Go・Rust・Rなどは公式サポートの対象で、C#(.NET)は二次、PHPは三次(保証なし)の扱いです。
- MITライセンスで商用利用も無料です。主要開発者が所属するDuckLabsは2026年9月1日付でAWSに合流しましたが、DuckDB本体は非営利のDuckDB Foundationが管理し、MITライセンスのまま続きます。
DuckDBの仕組み:プロセス内で動く列指向の分析エンジン
PostgreSQLやMySQLは、データベースサーバーを別プロセスとして起動し、アプリはネットワーク越しにSQLを送ります。DuckDBはこのサーバーを持たず、ライブラリとしてアプリのプロセスに読み込まれます。SQLiteと同じ組み込み型ですが、SQLiteが1行ずつの読み書き(OLTP)に向けて行単位でデータを持つのに対し、DuckDBは列単位でデータを持ち、数千行ずつまとめて処理するベクトル化実行で集計を速くしています。この「組み込み型で、分析用」という組み合わせが、DuckDBが「分析用のSQLite」と説明される理由です。OLTPとOLAPの違いそのものはOLAP(オーラップ)とはで整理しています。
読み書きできるファイル形式が広いことも特徴です。CSV・Parquet・JSONは標準でそのままクエリでき、拡張機能を入れるとSQLite・PostgreSQL・MySQLのデータベース、S3上のファイル、Iceberg・Delta Lakeのテーブルも読めます。列指向のファイル形式についてはParquetとはが詳しいです。
メモリの使い方にも既定値があります。memory_limit の既定は物理メモリの80%で、16GBのMacで確認すると 12.7 GiB でした。結合や並べ替えなどの中間データはこの上限を超えると一時ファイルへ退避されるため、メモリより大きいデータも処理できます。ただし退避できない処理もあり、すべてのクエリが成功する保証ではありません。
開発元とライセンス:CWI発・MIT・財団による管理
DuckDBは、アムステルダムにあるCWI(Centrum Wiskunde & Informatica)のDatabase Architecturesグループで、Mark RaasveldtとHannes Mühleisenが2018年に開発を始めました。v0.1は2019年にアムステルダムで開かれた学会SIGMODで発表され(GitHubのタグ v0.1.0 は2019年6月27日)、安定版の1.0.0は2024年6月3日に公開されています。
知的財産と商標は非営利のDuckDB Foundationが持ち、公式FAQは「有償のエンタープライズ版は存在しない」と明記しています。主要開発者を雇用する企業DuckLabs(旧称DuckDB Labs)は、2026年8月26日の発表どおり8月31日に手続きを終え、9月1日付でAWSに合流しました。発表文は、DuckDB・DuckLake・Quackが引き続きMITライセンスの無料OSSであり、DuckDB Foundationが管理を続けると述べています。商用利用やライセンスの前提は変わっていません。
DuckDBのバージョンとサポート期間:1.5.6・LTSの1.4・2.0の予定
DuckDBは3〜5か月ごとに機能追加版(1.x.0)を出し、その間にバグ修正版を重ねます。1.4.0からは1つおきの版が長期サポート(LTS)版になり、コミュニティサポートはリリースから少なくとも1年です。公式FAQとサポート方針のページは、2026年10月時点のサポート対象を「最新のLTS=1.4(1.4.5)」と「最新の安定版=1.5(1.5.6)」の2系列としています。
| 版 | 公開日 | 位置づけ | 系列のサポート終了 |
|---|---|---|---|
| 1.0.0 | 2024-06-03 | 最初の安定版 | 2024-09-09(終了済み) |
| 1.4.0 | 2025-09-16 | 最初のLTS版 | 2026-11-17 |
| 1.4.5 | 2026-06-17 | LTSの最新修正版 | 2026-11-17 |
| 1.5.0 | 2026-03-09 | 現行の機能版 | 2027-03-01 |
| 1.5.6 | 2026-09-28 | 現行の最新修正版 | 2027-03-01 |
| 2.0.0 | 2026-10-21(予定) | 次の機能版(暫定) | 未定 |
| 2.0.1 | 2026-11-18(予定) | 2.0の最初の修正版(暫定) | 未定 |
公開日はGitHub Releases、予定日とサポート終了日は公式のリリースカレンダーによります(2026年10月15日に確認)。カレンダーは「予定日は暫定で、延期することがある」としています。1.5系のサポート終了日はLTSの1.4系より後なので、いま1.4系で動いているシステムは、2.0を待たずに1.5.6へ上げてもサポート期間は短くなりません。なお、1.5系の終了日は、Internet Archiveに残る2026年10月10日時点の公式カレンダーでは2026年11月1日でした。その後2027年3月1日に延びており、外部の集計サイトendoflife.dateは10月15日時点でも2026年11月1日のままです。サポート期限は変わることがあるので、判断の直前に公式カレンダーで確かめてください。
2.0では、コマンドラインクライアント(CLI)に「エージェントモード」が入ると公式ブログ(Agent Mode in the DuckDB CLI、2026年10月9日)が説明しています。Claude CodeやCodex、Cursorなどが設定する環境変数を検出し、標準出力が端末ではなく、コマンドラインで出力形式を明示していない場合は、結果を罫線付きの表ではなく型名入りのMarkdown表で返し、エラーをJSONで出します。1,000行または10,000バイトを超える結果は先頭と末尾の20行だけを示し、省略したことを明記します。同じブログによると、TPC-Hの22問をClaude Codeに解かせた実験では、エージェントが読むDuckDBの出力が12.36万トークンから5.08万トークンへ59%減りました。ただし、毎回読み直すシステムプロンプトの方がはるかに大きいため、削減分は入力全体の約0.5%にとどまり、総費用や実行時間の差には表れなかったとしています。-agent と -no-agent で強制的に切り替えられます。
見落としやすいのがPythonの版との組み合わせです。PyPIのduckdbは1.5.0から Requires-Python >=3.10 になり、1.4.5までは3.9以上でした。macOS標準の /usr/bin/python3(3.9.6)で pip install duckdb するとエラーにならずに1.4.5が入るため、手元の版は SELECT version(); で確かめてから使ってください。
DuckDBの用途:ファイルの直接集計と他のデータベースの分析
DuckDBが最も効くのは、手元やS3にあるファイルをデータベースに取り込む手間をかけずに集計する場面です。ノートブックでのデータ探索、ETLの中間処理、BIツールや社内アプリの集計バックエンド、ブラウザ内での分析(DuckDB WASM)に使われています。pandasやPolarsのDataFrameをそのままテーブルとしてSQLで参照でき、結果をDataFrameに戻すこともできます。
Parquetファイルを取り込まずにSQLで集計する例
Pythonから500万行のParquetファイル(31.9MiB)を読み、店舗ごとの売上上位3件を出す例です。実行前に、後述の実測比較に掲載したデータ生成SQLとCOPY文を実行し、コード中のファイルパスを保存先に合わせてください。FROM にファイルパスを書くだけで読めます。GROUP BY ALL はSELECT句の集計していない列をまとめてGROUP BYにする省略記法です。DuckDBのほか、Snowflakeなども対応しています。
import duckdb
con = duckdb.connect() # 引数なし=インメモリ
print(con.sql("""
SELECT store_id, count(*) AS n, round(sum(amount), 2) AS total
FROM '/tmp/b.parquet'
GROUP BY ALL
ORDER BY total DESC
LIMIT 3
"""))
┌──────────┬───────┬──────────┐
│ store_id │ n │ total │
│ int64 │ int64 │ double │
├──────────┼───────┼──────────┤
│ 321 │ 5000 │ 274950.0 │
│ 642 │ 5000 │ 274900.0 │
│ 963 │ 5000 │ 274850.0 │
└──────────┴───────┴──────────┘
件数・合計・平均を求める別の集計では、Parquetから0.036秒(5回の中央値)、同じ内容のCSV(135.7MiB)から0.850秒(3回の中央値)でした。CSVは毎回文字列を解析して型を推定するため、同じデータを何度も集計するならParquetかDuckDBのデータベースファイルに変換しておく方が速く済みます。
SQLiteのデータベースをDuckDBから集計する例
sqlite拡張を使うと、既存のSQLiteファイルをそのままアタッチして集計できます。アプリはSQLiteのまま運用し、分析だけDuckDBで回す構成がとれます。
con.sql("INSTALL sqlite; LOAD sqlite;")
con.sql("ATTACH '/tmp/b.sqlite' AS lite (TYPE sqlite, READ_ONLY)")
con.sql("""
SELECT store_id, count(*) AS n, sum(amount) AS total
FROM lite.sales GROUP BY ALL ORDER BY total DESC LIMIT 3
""").fetchall()
500万行のSQLiteファイルに対して、この集計は0.303秒で終わりました。SQLite自身で同様の集計(平均も加え、GROUP BY ALL はSQLiteでは使えないため GROUP BY store_id と書いたもの)を実行すると5.850秒でした。SQLiteのファイルを読み出す時間を含めても、集計はDuckDB側で行う方が速いということです。PostgreSQLやMySQLにも同様の拡張(postgres・mysql)があります。
pandasのDataFrameをそのままSQLで集計する例
Pythonの変数に入っているpandasのDataFrameは、変数名をテーブル名として書くだけでSQLから参照できます。DuckDBのテーブルへ取り込む手順は要りません。結果は .df() でpandasのDataFrameとして受け取れます。
import duckdb
# df は500万行の pandas.DataFrame(id・store_id・sold_on・amount の4列)
res = duckdb.sql("""
SELECT store_id, count(*) AS n, sum(amount) AS total, avg(amount) AS avg
FROM df
GROUP BY ALL
ORDER BY total DESC
LIMIT 3
""").df()
# 比較に使ったpandasの書き方
res_pd = (df.groupby("store_id")["amount"]
.agg(["count", "sum", "mean"])
.sort_values("sum", ascending=False)
.head(3))
前の例と同じ500万行をpandas 3.0.6のDataFrameに読み込み(同じIntel Mac・Python 3.13・DuckDB 1.5.6、2026年10月15日に計測)、pandasの集計とDuckDBのSQLとで同じ結果を求めた時間です(5回の中央値・DuckDB側は結果をDataFrameへ戻す時間を含む)。
| 処理 | pandas | DuckDB(DataFrameを参照) | 差 |
|---|---|---|---|
| 店舗別の件数・合計・平均(上位3件) | 0.401秒 | 0.056秒 | DuckDBが約7倍速い |
| 月別の売上合計 | 0.683秒 | 0.095秒 | DuckDBが約7倍速い |
どちらも結果は同じで、上位3件は店舗321・642・963でした。DuckDBは集計を複数スレッドで並列に処理します。pandasの処理をすべて置き換える必要はなく、重い集計や結合だけをSQLに任せ、結果のDataFrameを可視化や機械学習にそのまま渡す、という分け方ができます。
複数ファイルの一括読み込みとDuckDBのSQLの便利な書き方
パスにワイルドカードを書くと、複数のファイルを1つのテーブルとして読めます。filename=true を付けると、各行がどのファイルから来たかを列で確認できます。次は月ごとに分けた3つのParquetファイルを読んだ結果です。
SELECT filename, count(*) AS n
FROM read_parquet('/tmp/s5741/data/sales_2025_*.parquet', filename = true)
GROUP BY ALL
ORDER BY filename;
┌───────────────────────────────────────┬────────┐
│ filename │ n │
│ varchar │ int64 │
├───────────────────────────────────────┼────────┤
│ /tmp/s5741/data/sales_2025_01.parquet │ 424669 │
│ /tmp/s5741/data/sales_2025_02.parquet │ 383572 │
│ /tmp/s5741/data/sales_2025_03.parquet │ 424669 │
└───────────────────────────────────────┴────────┘
DuckDBは、公式ドキュメントが「Friendly SQL」と呼ぶ省略記法を多く備えています。手元で動作を確かめたものを挙げます。
FROM sales LIMIT 2;:SELECT句を省いてFROMから書けます。全列を返します。SELECT * EXCLUDE (id) FROM sales;:指定した列だけを除いた全列を返します。QUALIFY row_number() OVER (PARTITION BY store_id ORDER BY amount DESC) = 1:ウィンドウ関数の結果で行を絞ります。店舗ごとの最高額の1行を、サブクエリなしで取り出せます(QUALIFYはSnowflakeやBigQueryにもあります)。SUMMARIZE sales;:列ごとの型・最小値・最大値・平均・欠損率などを1回で返します。
SUMMARIZEは手早くデータの形を見るのに便利ですが、種類数を示す approx_unique は推定値です。0〜999の1,000種類しかないstore_idで 1249、365日分しかないsold_onで 313 と出ました。正確な種類数が必要なら count(DISTINCT store_id) で数えてください。
SQLite・PostgreSQLとの違い:構成の比較とSQLiteとの実測
3つともSQLで操作できますが、対応する構文や関数、動作形態、得意な処理が異なります。
| 項目 | DuckDB | SQLite | PostgreSQL |
|---|---|---|---|
| 動作形態 | プロセス内 | プロセス内 | サーバー |
| データの持ち方 | 列指向 | 行指向 | 行指向 |
| 得意な処理 | 集計・結合(OLAP) | 小さな読み書き | 同時の読み書き(OLTP) |
| 同時に書けるプロセス | 1 | 1(ロックで順番待ち) | 多数 |
| ファイルの直接クエリ | CSV・Parquet・JSON | 標準では不可(CSVは拡張で可) | 拡張や外部テーブルが必要 |
500万行の実測:集計はDuckDB、1行検索はインデックスありのSQLiteが速い
同じ500万行(id・店舗ID・日付・金額の4列)をDuckDB 1.5.6とSQLite 3.53.1のファイルに入れ、Python 3.13から同じ問い合わせを投げた結果です。環境はIntel Mac(Core i9-9880H・16スレッド・メモリ16GB)で、DuckDBのスレッド数は既定のままです。時間はPythonの time.perf_counter() で問い合わせの発行から結果の取得までを測り、DuckDBは5回、SQLiteは3回の中央値です(いずれも同じ問い合わせを続けて実行したもので、初回だけの値ではありません)。データはDuckDBで次のように生成し、同じ行をSQLiteへ入れました(前章のParquet・CSVもこのテーブルから書き出したものです)。
CREATE TABLE sales AS
SELECT i AS id,
i % 1000 AS store_id,
DATE '2025-01-01' + CAST(i % 365 AS INTEGER) AS sold_on,
((i * 7919) % 10000) / 100.0 AS amount
FROM range(5000000) t(i);
COPY sales TO '/tmp/b.parquet' (FORMAT parquet);
COPY sales TO '/tmp/b.csv' (HEADER);
| 処理 | DuckDB | SQLite | 差 |
|---|---|---|---|
| 店舗別の件数・合計・平均(上位3件) | 0.015秒 | 5.850秒 | DuckDBが388倍速い |
| 月別の売上合計 | 0.193秒 | 8.595秒 | DuckDBが45倍速い |
| idで1行を取得(SQLiteはインデックスあり) | 1.86ミリ秒 | 0.027ミリ秒 | SQLiteが約70倍速い |
| データベースファイルのサイズ | 30.5MiB | 222.5MiB | DuckDBが約7分の1 |
集計では、DuckDBは必要な列だけを圧縮された状態で読み、複数スレッドで並列に処理します。SQLiteは行単位でデータを持つため、今回のようにインデックスの無い列で全行を集計すると、使わない列も含めて読むことになります(集計に使う列だけのカバリングインデックスを作れば、この差は縮められます)。ファイルサイズの差には列単位の圧縮のほか型とインデックスも効いています。日付はDuckDBではDATE、SQLiteではTEXTで保存し、SQLite側の222.5MiBにはidのインデックスも含まれます。
逆に、idで1件を引く処理は、idにインデックスを作成したSQLiteが、インデックス(DuckDBではART)を作っていないDuckDBより約70倍速く終わりました。今回測定したのはインデックス条件の異なる1行検索であり、更新処理の性能は比較していません。少数行の読み書きを頻繁に行う業務アプリでは、この結果だけで置き換えを判断せず、インデックス条件をそろえ、実際の更新処理も含めて比較する必要があります。判断基準は単純で、「多くの行をまとめて集計するか」「少しの行を頻繁に読み書きするか」です。組み込み型でOLTP寄りの選択肢には、SQLite互換のTursoもあります。
PostgreSQLとの使い分け:同時書き込みと分析処理の分担
PostgreSQLは複数のアプリや利用者が同時に書き込む業務データの置き場所で、DuckDBはそのデータを取り出して集計する側に向きます。両者は競合というより組み合わせて使うもので、postgres拡張を使うとDuckDBからPostgreSQLのテーブルを直接読んで集計できます。本番のPostgreSQLに重い集計を投げたくないときに、DuckDBで読んでParquetに書き出し、以降の分析はファイルに対して行う、という分担が典型です。
pandas・Polars・BigQueryとの位置関係
DuckDBと比べられることが多いツールとの違いを、どこで動き何で操作するかで整理します。
| ツール | 操作方法 | 動く場所 | 向く規模 |
|---|---|---|---|
| DuckDB | SQL(Python等からも) | 手元のプロセス内 | 1台に載る範囲 |
| pandas | Python API | 手元のプロセス内 | メモリに載る範囲 |
| Polars | Python・Rust API | 手元のプロセス内 | 1台に載る範囲 |
| BigQuery | SQL | Google Cloud | TB〜PB |
| ClickHouse | SQL | サーバー(クラスタ) | TB〜PB・常時稼働 |
pandasやPolarsとは排他ではなく、前述のとおりDataFrameの変数名をそのままSQLのテーブル名として参照できるため、前処理はSQL、機械学習の入力はDataFrameと分けて使えます。BigQueryやClickHouseは、複数人が常時使う大規模データの共有基盤です。データが1台のディスクに収まり、使う人が1人か少人数なら、DuckDBでクラウドの費用をかけずに済みます。Rust製の同種のクエリエンジンにはApache DataFusionがあります。
対応言語とクライアントAPI:公式サポートの3段階
公式ドキュメントのClient Overviewは、各言語のクライアントを3段階に分けています。Primaryは新機能が最初に入りコミュニティサポートの対象、Secondaryは新機能は入るがサポート対象外、Tertiaryは機能もサポートも保証されません。
| 区分 | クライアント |
|---|---|
| Primary(言語) | Python、R、Java(JDBC)、Go、Rust、Node.js(node-neo) |
| Primary(その他) | C、CLI、ODBC、Wasm |
| Secondary | ADBC(Arrow)、C#(.NET)、C++ |
| Tertiary | Dart、Julia、PHP、PHP(PDO)、Swift |
JavaはJDBCドライバが公式に保守されているので、Spring BootなどからJDBCの流儀のまま使えます。C#のクライアントはコミュニティの保守者(Giorgi)によるものですが、2026年9月時点で1.5.5まで追随しています。PHPはTertiaryなので、LaravelなどのPHPアプリから本番で使う場合は、ライブラリの保守状況を自分で確認する前提になります。PHPアプリなら、DuckDBをバッチ処理側に置いて結果をファイルやRDBに書き出し、アプリはそれを読むだけにする方が保守の負担は小さく済みます。全クライアントでSQLの文法とデータベースファイルの形式は共通です。
DuckDBを採用しない方がよい場面:複数プロセスからの書き込み
DuckDBの最大の制約は同時実行のモデルです。公式ドキュメントのConcurrencyによると、読み書きモードで開けるのは1プロセスだけで、読み取り専用モードなら複数プロセスから開けますが、その間はどのプロセスも書き込めません。1つのプロセスの中では複数スレッドから書き込めますが、同じ行を同時に更新または削除する場合などには、トランザクションの競合が発生します。
実際に、あるPythonプロセスがデータベースファイルを開いたまま、別のプロセスから開こうとすると次のエラーになりました。読み取り専用(read_only=True)で開こうとしても同じです。
IO Error: Could not set lock on file "/private/tmp/lock.duckdb": Conflicting lock is held in .../python3.13 (PID 12889) by user shichiza. See also https://duckdb.org/docs/stable/connect/concurrency
書き込み側のプロセスが接続を閉じた後は、2つのプロセスが同時に読み取り専用で開けました。つまり「1つのプロセスが書いている間は、ほかのプロセスは読むこともできない」のが既定の動作です。Webアプリの複数ワーカーが同じDuckDBファイルに書き込む構成や、夜間バッチが書き込み中にダッシュボードが同じファイルを読む構成は、そのままでは成り立ちません。
複数の利用者で同じデータを読み書きしたい場合、公式が示す選択肢は2つです。
- DuckLake:PostgreSQLをカタログ(メタデータの置き場所)にし、データはParquetファイルとして持つ形式です。仕様とDuckDBの実装のv1.0が2026年4月に公開され、公式は本番利用に耐えるとしています。
- Quack:DuckDBをクライアント・サーバー型で動かすリモートプロトコルです。1.5.2時点でベータ版で、2.0で成熟する見込みとされています。
このほか、ネットワークドライブや異なるOSから共有したディレクトリにデータベースファイルを置くと、ファイルロックが正しく働かないことがあると公式は注意しています。
MotherDuck:DuckDBをクラウドで使うサービス
MotherDuckは、DuckDBを使ったクラウドとローカルのハイブリッド型分析基盤を提供するベンチャー企業です。DuckDB公式FAQによると、MotherDuckはDuckLabsに開発を委託しており、DuckLabsはMotherDuckの株式の一部を持っています。DuckDBのクエリをクラウド上で実行でき、複数人でのデータ共有もできるので、前の章の同時実行の制約をサービス側で解消する選択肢になります。
2026年9月29日時点の料金ページでは、個人向けのLiteが$0から(ストレージ10GB・月10時間の計算時間を含む)、本番向けのBusinessが組織あたり月$250+従量課金です。DuckDB本体はMotherDuckを使わなくても機能が欠けることはなく、MotherDuckは「共有と運用を任せたいとき」の選択肢です。
よくある質問
DuckDBの読み方は?
「ダックディービー」です。「duck db」「ダックdb」と分けて書かれることもありますが、正式な表記はDuckDBです。名前は、飛ぶ・歩く・泳ぐのどれもこなし、何でも食べて生き延びるアヒル(duck)のように、柔軟で丈夫なデータベースを目指したことに由来すると公式FAQは説明しています。
DuckDBは無料で商用利用できますか?
できます。MITライセンスで、有償のエンタープライズ版もありません。DuckLabsのAWS合流後も、DuckDB FoundationがMITライセンスのまま管理を続けると発表されています。
DuckDBはOLTPやNoSQLの代わりに使えますか?
向きません。DuckDBはリレーショナル(SQL)の分析用データベースです。本記事の1行検索では、SQLiteはインデックスあり、DuckDBはARTインデックスなしという条件で、SQLiteが約70倍速い結果でした。また、通常のインプロセス利用では、同じDuckDBファイルを読み書きモードで開けるのは1プロセスです。業務データの保存はPostgreSQLやSQLiteに任せ、DuckDBは集計側に置くのが基本です。JSONはそのまま読み込めるので、ドキュメント形式のデータを集計する用途には使えます。
DuckDBはPHPやJava、C#から使えますか?
使えます。Java(JDBC)は公式サポート対象のPrimary、C#(.NET)は新機能が追随するSecondary、PHPは保証のないTertiaryです。PHPから使う場合は、ライブラリの更新が止まっていないかを先に確認してください。
pandasとDuckDBはどちらを使えばよいですか?
併用するのが現実的です。本記事の実測では、500万行のDataFrameに対する集計はDuckDBのSQLの方が約7倍速く終わりました。一方、行ごとの細かい加工や、DataFrameを前提にした可視化・機械学習のライブラリとのやりとりはpandasの方が自然に書けます。重い集計と結合をDuckDBに任せ、結果をDataFrameで受け取って続きをpandasで書く、という使い分けをおすすめします。
メモリより大きいデータも扱えますか?
多くの場合は扱えます。結合・集計・並べ替えなどは中間データを一時ファイルへ退避して処理を続けます。ただし memory_limit(既定は物理メモリの80%)はバッファマネージャーに対する上限で、プロセス全体の上限ではありません。上限の外でメモリを確保する処理もあり、OSにプロセスを落とされることがあるため、公式ガイドはその場合に上限を下げるよう勧めています。退避が増えるほど遅くもなるので、必要な列と期間に絞って読むのが前提です。