0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

高速分析データベース「DuckDB」を使ってみた

Last updated at Posted at 2025-08-06

私自身、業務の一環として大量のログを扱う場面があります。その際、もっと簡単に使用できて汎用性のある分析ツールがないか考えていました。

そこで調べてみた結果、DuckDBに白羽の矢が立ちました。

データ分析の現場では、大量のデータを効率的に処理できるツールの需要が高まっています。従来のRDBMSでは重すぎる、かといってBigQueryのようなクラウドサービスを使うほどでもない、そんな中間的なニーズに応えるデータベースとして注目を集めているのがDuckDBです。

本記事では、DuckDBの特徴から実際の導入・使用方法まで、実体験を交えながら紹介していきます。

DuckDBとは

DuckDBは、OLAP(分析処理)に特化したインメモリ分析データベースです。2019年にオープンソースとして公開され、「分析のためのSQLite」というコンセプトで開発されています。

以下のような特徴があります。

  • 軽量かつ高速
  • 豊富なデータ形式サポート
  • SQLの高い互換性

導入・実践

インストール

公式インストールページはこちらです。他のインストール方法が載っています。

筆者はhomebrewを使用してインストールしています。

brew install duckdb

本記事では、DuckDBは v1.3.1 で進めていきます

検証ファイル

こちらは生成AIで作成してもらったログjsonファイルになります。

logs.json
{"timestamp":"2025-08-01T09:00:23.685Z","status_code":201,"user_id":"user_00425","endpoint":"/home","message":"New record added"}
{"timestamp":"2025-07-06T04:37:37.831Z","status_code":403,"user_id":null,"endpoint":"/help","message":"Forbidden access"}
{"timestamp":"2025-07-05T03:11:48.922Z","status_code":200,"user_id":null,"endpoint":"/api/auth/logout","message":"User authenticated"}
{"timestamp":"2025-07-12T03:20:38.234Z","status_code":201,"user_id":null,"endpoint":"/home","message":"New record added"}
{"timestamp":"2025-07-11T04:49:26.449Z","status_code":200,"user_id":null,"endpoint":"/api/settings","message":"User authenticated"}
{"timestamp":"2025-07-18T23:44:46.939Z","status_code":204,"user_id":null,"endpoint":"/about","message":"Update completed"}
{"timestamp":"2025-07-18T09:06:24.734Z","status_code":200,"user_id":"user_11746","endpoint":"/api/reports","message":"Search results returned"}
{"timestamp":"2025-07-09T17:03:48.701Z","status_code":403,"user_id":null,"endpoint":"/api/auth/logout","message":"Insufficient permissions"}
{"timestamp":"2025-07-30T05:22:34.571Z","status_code":200,"user_id":null,"endpoint":"/contact","message":"Search results returned"}
{"timestamp":"2025-07-27T10:31:18.351Z","status_code":200,"user_id":null,"endpoint":"/api/search","message":"Request processed successfully"}

基本操作

実際にDuckDBを使用してログ解析してみましょう。

DuckDBを起動

duckdb

ファイルの読み込み

単数
select * from read_json('logs.json');
output
┌┌──────────────────────────┬─────────────┬────────────┬──────────────────┬────────────────────────────────┐
│        timestamp         │ status_code │  user_id   │     endpoint     │            message             │
│         varchar          │    int64    │  varchar   │     varchar      │            varchar             │
├──────────────────────────┼─────────────┼────────────┼──────────────────┼────────────────────────────────┤
│ 2025-08-01T09:00:23.685Z │         201 │ user_00425 │ /home            │ New record added               │
│ 2025-07-06T04:37:37.831Z │         403 │ NULL       │ /help            │ Forbidden access               │
│ 2025-07-05T03:11:48.922Z │         200 │ NULL       │ /api/auth/logout │ User authenticated             │
│ 2025-07-12T03:20:38.234Z │         201 │ NULL       │ /home            │ New record added               │
│ 2025-07-11T04:49:26.449Z │         200 │ NULL       │ /api/settings    │ User authenticated             │
│ 2025-07-18T23:44:46.939Z │         204 │ NULL       │ /about           │ Update completed               │
│ 2025-07-18T09:06:24.734Z │         200 │ user_11746 │ /api/reports     │ Search results returned        │
│ 2025-07-09T17:03:48.701Z │         403 │ NULL       │ /api/auth/logout │ Insufficient permissions       │
│ 2025-07-30T05:22:34.571Z │         200 │ NULL       │ /contact         │ Search results returned        │
│ 2025-07-27T10:31:18.351Z │         200 │ NULL       │ /api/search      │ Request processed successfully │
├──────────────────────────┴─────────────┴────────────┴──────────────────┴────────────────────────────────┤
│ 10 rows                                                                                       5 columns │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────┘
複数

ワイルドカードを使用して複数読み込みが可能です。
filenameをつけることで、どのファイルから読み込んだデータか表示されるようになります。

select * from read_json('*.json', filename = true);
output
┌──────────────────────────┬─────────────┬────────────┬──────────────────┬────────────────────────────────┬─────────────┐
│        timestamp         │ status_code │  user_id   │     endpoint     │            message             │  filename   │
│         varchar          │    int64    │  varchar   │     varchar      │            varchar             │   varchar   │
├──────────────────────────┼─────────────┼────────────┼──────────────────┼────────────────────────────────┼─────────────┤
│ 2025-08-01T09:00:23.685Z │         201 │ user_00425 │ /home            │ New record added               │ logs-2.json │
│ 2025-07-06T04:37:37.831Z │         403 │ NULL       │ /help            │ Forbidden access               │ logs-2.json │
│ 2025-07-05T03:11:48.922Z │         200 │ NULL       │ /api/auth/logout │ User authenticated             │ logs-2.json │
│ 2025-07-12T03:20:38.234Z │         201 │ NULL       │ /home            │ New record added               │ logs-2.json │
│ 2025-07-11T04:49:26.449Z │         200 │ NULL       │ /api/settings    │ User authenticated             │ logs-2.json │
│ 2025-07-18T23:44:46.939Z │         204 │ NULL       │ /about           │ Update completed               │ logs-2.json │
│ 2025-07-18T09:06:24.734Z │         200 │ user_11746 │ /api/reports     │ Search results returned        │ logs-2.json │
│ 2025-07-09T17:03:48.701Z │         403 │ NULL       │ /api/auth/logout │ Insufficient permissions       │ logs-2.json │
│ 2025-07-30T05:22:34.571Z │         200 │ NULL       │ /contact         │ Search results returned        │ logs-2.json │
│ 2025-07-27T10:31:18.351Z │         200 │ NULL       │ /api/search      │ Request processed successfully │ logs-2.json │
│ 2025-08-01T09:00:23.685Z │         201 │ user_00425 │ /home            │ New record added               │ logs.json   │
│ 2025-07-06T04:37:37.831Z │         403 │ NULL       │ /help            │ Forbidden access               │ logs.json   │
│ 2025-07-05T03:11:48.922Z │         200 │ NULL       │ /api/auth/logout │ User authenticated             │ logs.json   │
│ 2025-07-12T03:20:38.234Z │         201 │ NULL       │ /home            │ New record added               │ logs.json   │
│ 2025-07-11T04:49:26.449Z │         200 │ NULL       │ /api/settings    │ User authenticated             │ logs.json   │
│ 2025-07-18T23:44:46.939Z │         204 │ NULL       │ /about           │ Update completed               │ logs.json   │
│ 2025-07-18T09:06:24.734Z │         200 │ user_11746 │ /api/reports     │ Search results returned        │ logs.json   │
│ 2025-07-09T17:03:48.701Z │         403 │ NULL       │ /api/auth/logout │ Insufficient permissions       │ logs.json   │
│ 2025-07-30T05:22:34.571Z │         200 │ NULL       │ /contact         │ Search results returned        │ logs.json   │
│ 2025-07-27T10:31:18.351Z │         200 │ NULL       │ /api/search      │ Request processed successfully │ logs.json   │
├──────────────────────────┴─────────────┴────────────┴──────────────────┴────────────────────────────────┴─────────────┤
│ 20 rows                                                                                                     6 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

WHERE句を使用した絞り込み

エラーコードのみを表示させるようにしてみましょう。

select * from read_json('logs.json') where status_code >= 400;
output
┌──────────────────────────┬─────────────┬─────────┬──────────────────┬──────────────────────────┐
│        timestamp         │ status_code │ user_id │     endpoint     │         message          │
│         varchar          │    int64    │ varchar │     varchar      │         varchar          │
├──────────────────────────┼─────────────┼─────────┼──────────────────┼──────────────────────────┤
│ 2025-07-06T04:37:37.831Z │         403 │ NULL    │ /help            │ Forbidden access         │
│ 2025-07-09T17:03:48.701Z │         403 │ NULL    │ /api/auth/logout │ Insufficient permissions │
└──────────────────────────┴─────────────┴─────────┴──────────────────┴──────────────────────────┘

テーブル作成

毎回直接ファイルを読み込むだけでなく、読み込みファイルを元にテーブルを作成できます。

-- テーブル作成
create table logs as select * from read_json('logs.json');
-- テーブル読み込み
select * from logs;

テーブルを作成することでパフォーマンスの大幅向上が見込めます。

所感

サーバーの起動や設定ファイルの編集が不要で、インストールも簡単ですぐに使い始められる手軽さは大きなメリットです。
データ分析の初期段階で「とりあえず試してみる」際の障壁が非常に低いです。

また実際に100万件のデータを対象に集計処理を試したところ、とても高速に検索ができました。RDBが行指向に対し、DuckDBは列指向なのでそこにも差が出てきているのかと思います。

さいごに

DuckDBは、データ分析における「ちょうど良い」ソリューションとして非常に有用なツールです。

今回はjsonファイルを使用しましたが、他にも多くの拡張子に対応しています。詳しくは参考サイト公式から確認してみてください。

導入も簡単であるため、分析ツールとして気軽に試してみてはいかがでしょうか。

参考サイト

GoQSystemでは一緒に働いてくれる仲間を募集中です!

ご興味がある方は以下リンクよりご確認ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?