🦆

なぜ DuckDB を採用したのか

2024/11/17に公開

概要

なぜ 自社 で DuckDB を採用したのかを、雑に書いていきます。

まとめ

  • DuckDB / DuckDB-Wasm を利用する事で中小規模のサービスであれば、ログ解析や統計情報の可視化を低コストで提供することができる
  • DuckDB を go-duckdb 経由で利用する事で、HTTP リクエスト単位での DuckDB を利用できる
  • DuckDB-Wasm と OPFS を利用する事で、クライアント側での統計情報のため込みができるようになる

解決したい課題

解決したい課題は基本的にサービスの運用費を抑えるということです。中小規模のサービスでは運用費が大きな課題になります。

自社パッケージ向けのログ解析ツール

自社パッケージ製品は多くの JSON Lines 形式 (移行 JSONL) でログを出力します。
顧客からの問い合わせに対して、共有して貰ったログを解析して問題を特定することがあります。

この際、今までは jq や Python を使って色々頑張っていましたが、 DuckDB CLI を利用する事で、SQL でログを解析することができるようになりました。

顧客から送られてくるログはローテーションにより、分割されていることが多く、 .gz や .zst で圧縮されています。

DuckDB を使うと CREATE TABLE logs AS SELECT * FROM read_json_auto('*.jsonl.gz'); といった感じで 圧縮された複数ファイル を一気に読み込み、テーブルを作成できます。あとは SQL で解析するだけです。

この SQL で解析というのがとても大事です。SQL を読み書きできる人は多いです。また、DuckDB はインストールも簡単ということもあり、ログ解析ツールとしては最適だと思います。

ネットワークが閉じている環境でも、DuckDB CLI を利用することで、ログ解析が気軽にできます。

さらに、顧客にも、DuckDB を利用することをオススメしやすいです。こちらから「今後似たような問題が起きた場合はこの SQL を実行して結果を確認してみてください」というように提案することができます。

DuckDB で JSON Lines 形式のログを精査する

自社サービス向けのログ保存

自社パッケージを利用した自社サービスの課題として、大量に出力されるログをどう保存するか、という課題がありました。

サービス設計時にログを気軽に解析したいと考え、マネージドの TSDB (Time Series Database) を採用しました。しかし、TSDB のマネージドサービスは多くの場合 CPU とディスク容量で課金されるため、今後費用を抑えることが難しいと感じていました。

また、RDB と TSDB の ハイブリッドな製品 を採用したことにより、TSDB 利用時の負荷が RDB に影響を与えることもありました。

そこで、ログ保存を Fluent Bit から S3 または S3 互換のオブジェクトストレージ(以降オブジェクトストレージ)に保存して、DuckDB や DuckdB-Wasm を利用して解析するという方法を採用することにしました。

オブジェクトストレージには自社サービスで利用している Akamai Connected Cloud が提供している Object Storage を利用しています。費用が 250 GB 単位で月 $5 です。転送量は月 1 TB まで付与されており、それ以降の転送量費用は月 1 TB で $5 です。

ちなみに将来的に 1 バケットのファイルが最大 100 億、サイズが最大 5 PB まで増えるようです。

オブジェクトストレージはデリートポリシーを利用する事で、自動で削除も難しくありません。削除時に RDB に負荷をあたえないのもとても良いです。

解析自体は、ダッシュボードから 特定の状況のログを要求される までは何もしないという戦略をとりました。そのため、サービスの CPU リソースの消費を抑えられます。

また、解析自体は後述する DuckDB-Wasm を利用する事で、サービス側のリソースを利用しなくて良くなりました。

サービス側で利用するリソースは HTTP リクエスト単位で、オブジェクトストレージから特定の状況のログを解析して、Parquet ファイルにして、オブジェクトストレージに保存し、その Presigned URL を生成してブラウザに渡すだけです。既に Parquet ファイルがあれば、Presigned URL 生成して渡すだけで良いです。

ちなみに、HTTP リクエスト単位の DuckDB 処理には go-duckdb を利用することで、並列での DuckDB の利用ができるようになっています。

DuckDB/DuckDB-Wasm を利用した低コストでの可視化

自社サービス向けの統計情報の可視化

自社サービスでは、自社パッケージのログを利用した可視化の仕組みを提供したいと考えていました。
自社パッケージ製品は音声や映像、データのリアルタイムな配信を行うための製品ということもあり、多くのログが出力されます。

このログをデータベースにため込んで解析を提供するとなると、費用がとても高くなります。実際、似たようなサービスを提供している企業は、ログ解析だけで追加費用を請求しているところが多いです。

ただ、可視化は 困ったとき にしか見ないことが多く、可視化機能は追加費用なしで提供したいと考えていたため、可視化にかかる費用を抑えることが重要でした。

そこで、自社サービス向けの統計情報を可視化するために、DuckDB-Wasm を利用することにしました。 DuckDB-Wasm は WebAssembly で動作する DuckDB で、ブラウザ上で SQL を実行することができます。

つまり、サービス側のリソースを使わずに、つまりブラウザ上でクライアント側のリソースを利用して SQL を実行することができるようになりました。

ログの保存は前述の通り gzip 化してオブジェクトストレージに保存しており、さらに DuckDB を利用して集計し Parquet (圧縮は Zstandard) 形式でオブジェクトストレージに保存しています。

これによりさらに圧縮でき、オブジェクトストレージと転送量の費用を抑えることができるようになりました。

今後やりたい事

DuckDB や DuckDB-Wasm を利用することで、今後も様々な事をやりたいと考えています。
DuckDB は組み込み OLAP ということもあり、様々な場所で活躍できるのが本当に良いです。

クライアント側での統計情報のため込み

リアルタイム配信側のクライアントでしか取れない統計情報が多くあります。
この統計情報を毎回サーバ経由や、オブジェクトストレージにアップロードしていたらきりがありません。

そのため、クライアント側でため込むという仕組みを実現したいと考えていました。
モバイルやデスクトップクライアントであれば、 SQLite を組み込むなどで実現できたのですが、ブラウザでは WebSQL が廃止され、 IndexedDB は使いにくいという課題がありました。

DuckDB-Wasm も現時点ではオンメモリ上でのみで動作するため、データの永続性がありません。将来的に OPFS に対応することで、この課題を解決することができるようになります。

クライアントの統計情報を細かく取ることで、サーバ側のリソースを節約することができるようになりますし、より細かい解析ができるようになると考えています。

自社パッケージ用の可視化ツール

今まで自社製品の可視化ツールとして、TSDBGrafana を利用してもらう仕組みを提供していたのですが、運用コストや TSDB の性能が課題になっていました。

そのため、今後は DuckDB / DuckDB-Wasm を利用した、ログベースの可視化ツールを提供する事を検討しています。

  • 本番環境はログを Fluent Bit を利用して、オブジェクトストレージへ保存する
  • 検証環境ばそのまま DuckDB CLI で収集、解析して Parquet にしてオブジェクトストレージへ保存する
  • 可視化は Vite と Parquet ファイルをダウンロードして DuckDB-Wasm を利用して解析する

オブジェクトストレージは MinIO を利用することで、ローカルや検証環境の構築コストを抑えることができると考えています。

オープンソースの S3 互換オブジェクトストレージ MinIO を DuckDB で使う

雑感

DuckDB は自社にとって、多くの課題を解決してくれる素晴らしいツールだと感じています。

既に、自社サービスの管理画面には DuckDB / DuckDB-Wasm を導入しています。SQL エディターも CodeMirror を利用して用意しています。

Image from Gyazo

このように、SQL を書くことで、好きなように情報を表示できるようになりました。
管理画面で DuckDB-Wasm を利用しており、Parquet ファイルの生成も「要求されてから」なので、サービス側の負荷はほとんどありません。

今後は他のログとの関連付けや、グラフツールを使っての可視化などを検討しています。

ちなみにサービスのバックエンドは Akamai Connected Cloud の月 $5 のインスタンスです。

Discussion