アイキャッチ画像: JavaScriptでOLAP:ライブラリと実践例

JavaScriptでOLAP:ライブラリと実践例

公開日:

読了時間: 2 min

テーマ: テクノロジー

著者: Leandro Valencia

#olap javascript#duckdb wasm#ブラウザ分析#apache arrow#分析データベース

JavaScriptでOLAP型分析をする方法。DuckDB-Wasm、Apache Arrow、Arquero、Perspective、SQL.js、TinyBaseの例と使い分けを解説。

目次

全体像:フルエンジンと軽量ツール

ライブラリを一つずつ見る前に、役立つ区別があります。JavaScriptには「本番データベースを叩かずにデータを集計したい」に対する解決策が二種類あります。

WebAssemblyにコンパイルされた本物のOLAPエンジン。 カラム型ストレージ、ベクトル化、クエリオプティマイザ付きの分析SQLを実行します。ClickHouseやBigQueryと同じ系統ですが、ブラウザやNodeのプロセス内で動きます。代表格はDuckDB-Wasmです。

メモリ上の変換・集計ツール。 データベースエンジンではありません。すでに読み込まれたデータ構造(配列、Arrowテーブル、リアクティブストア)を、groupBysum、ピボットのような操作で扱うライブラリです。Arquero、Perspective、TinyBaseがここに入り、それぞれアプローチが違います。

SQL.jsはその中間です。本物のデータベースエンジン(SQLite)ですが、行指向であってカラム型ではないため、純粋な分析負荷では同じようにはスケールしません。それでも軽量な代替としてよく使われます。

DuckDB-Wasm:ブラウザ上の本格OLAPエンジン

DuckDB-Wasmは、OLAPガイドで「1台のマシンに収まるデータセットのデフォルト選択肢」として触れた組み込み分析エンジンDuckDBを、WebAssemblyにコンパイルしたものです。サーバーなしでブラウザでもNodeでも動き、ネイティブ版と同じベクトル化カラム型エンジン、同じPostgreSQL互換SQL方言を持ちます。

このリストで最も強力な選択肢です。OLAPの模倣ではなく、本物のクエリオプティマイザであり、Parquet、CSV、JSONを直接読めます。HTTP range requestsにも対応するので、ファイル全体をダウンロードする必要はありません。

使うべきとき: 集計、JOIN、ウィンドウといった本物のSQLを、中規模データセット(数MBから数百MB程度)に対してクライアント上で、バックエンド基盤なしで実行したいとき。データエクスポートを読み込む埋め込み分析ダッシュボード、クライアント側のデータ探索ツール、あるいはファイルがすでにユーザーのブラウザにあるのに重いクエリをサーバーへ送るのを避けたい場合の、自然な選択です。

エンジンの初期化と接続が済んだあと、Parquetファイルに対するクエリはおおむね次のように見えます。

const result = await connection.query(`
  SELECT pais, SUM(importe) AS ingresos
  FROM read_parquet('ventas.parquet')
  GROUP BY pais
  ORDER BY ingresos DESC
`);

console.table(result.toArray());

初期化(適切なWebAssemblyバンドルの選択、ワーカーの起動、接続のオープン)は手順が多く、バージョン間で変わるので、ここでは再現しません。インストールする版の正確なセットアップは、DuckDB-Wasmの公式ドキュメントを確認してください。

Apache Arrow (JS) + Arquero:カラム型形式とdplyr風の変換

この2つは一緒に使われることが多く、別々に理解しておくとよいです。

Apache Arrowはクエリエンジンではありません。言語をまたいで標準化されたメモリ上のカラム型データ形式です(Python、R、Java、C++、JavaScriptなどに実装があります)。価値は、DuckDB-Wasmを含む多くのデータツールがArrowを直接読み書きできることにあります。JSONへシリアライズしたり構造を組み直したりせず、同じメモリレイアウトを共有してデータを渡せます。

Arqueroは、Rのdplyrに明示的に着想を得たJavaScript向けデータ変換ライブラリです。カラム型テーブル——配列、型付き配列、Arrowカラム——の上で動き、フィルタ、グループ化、集計、結合といった動詞のチェーン可能なAPIを提供します。

使うべきとき: すでにArrow形式のデータがある(たとえばPythonパイプラインから書き出した、あるいはDuckDB-Wasmが返した)状態で、SQLを書かずにJavaScript上でロールアップや集計をチェーンしたいとき。JSのデータノートブック、対話的な探索ツール、あるいはチームがすでにdplyr/pandasの発想で動いていてSQLよりその構文を好む場合に向きます。

すでに読み込まれたテーブルに対する、Arqueroでの集計の簡略例です。

import { table } from 'arquero';

const ventas = table({
  pais: ['ES', 'MX', 'ES', 'AR'],
  importe: [42, 17, 88, 12],
});

const resumen = ventas
  .groupby('pais')
  .rollup({ ingresos: (d) => op.sum(d.importe) });

console.log(resumen.objects());

正確なimport API、集計関数名(op.sumop.meanなど)、fromArrow()でArrowテーブルを読み込む方法は、Arqueroの公式ドキュメントで確認した方がよいです。バージョンや、Arrow同梱バンドルを使うか別途importするかで変わります。

Perspective:リアルタイムダッシュボード向けピボットエンジン

PerspectiveはC++で書かれWebAssemblyにコンパイルされた集計・ピボットエンジンで、JavaScriptバインディングがあります。J.P. Morgan社内の金融ダッシュボード向けに生まれ、現在はFINOS財団のもとでオープンソースになっています。

このリストの他の選択肢と違うのは、リアルタイムで変わるデータ向けに設計されている点です。更新のストリーミング、ピボットテーブルのような対話的なピボット(行と列のグループ化、集計の適用、並べ替え)をサポートし、ページに差し込める独自のビジュアルコンポーネント(<perspective-viewer>)も付属します。

使うべきとき: エンドユーザーがビューを操作する——ディメンションをドラッグし、集計を変え、フィルタする——対話的ダッシュボードで、裏のデータがライブ更新される場合です。トレーディングパネル、運用メトリクスのモニター、プロダクトに埋め込んだBIなどが典型です。一度きりのクエリを走らせて固定の結果を出すだけなら、必要以上のエンジンです。その用途にはDuckDB-WasmやArqueroの方が合います。

SQL.js:WebAssembly上のSQLite。簡単だがカラム型ではない

SQL.jsはSQLiteをWebAssemblyにコンパイルしたもので、バックエンドなしでブラウザ内に完全なSQLiteデータベースを持てます。このリストではおそらく最も古参で、基本的なSQLを知っていれば一番導入しやすいライブラリです。

限界については正直である必要があります。SQLiteはPostgresやMySQLと同じ行指向のデータベースです。カラム型ストレージもベクトル化もなく、何百万行をスキャンして集計するためのオプティマイザもありません。用語の技術的な意味では、OLAPエンジンではありません。

それでも、クライアント上の小さな分析の軽量な代替としてよく使われます。数千行から数万行程度なら、本物のカラム型エンジンとの性能差は目立たず、利点はライブラリの単純さと成熟度です。

使うべきとき: ブラウザ上の小さなデータセットの探索分析、素早いプロトタイプ、あるいは何百万行を集計する性能より、書き込みやトランザクションを含む完全なSQLが欲しいとき。データセットがそれを超えて大きくなったら、DuckDB-Wasmへ移行してください。

TinyBase:軽量なリアクティブストアであり、OLAPエンジンではない

TinyBaseはJavaScriptアプリケーションの状態向けに設計されたリアクティブなデータストアで、ライブラリサイズが非常に小さいです。分析エンジンとしては設計されていません。主目的は状態の同期、ローカル永続化、リアクティビティ(データが変わるとUIが自分で更新されること)で、分析データベースというより状態管理ライブラリに近い精神です。

このリストに入れるのは、テーブル上のカウント、合計、平均といった単純な集計ユーティリティがあり、小さなアプリでは、本来もっと重いエンジンを立てるようなニーズをカバーできるからです。

使うべきとき: 必要な「分析」が、すでにアプリ状態にあるデータへの単純な集計——カウンタ、合計、ライブ更新される平均——であり、それだけのために本格SQLエンジンを足したくないとき。多次元ダッシュボードやアドホッククエリに見えるものには選びません。

比較早見表

ライブラリ 概要 本物のOLAPエンジン 向いている用途
DuckDB-Wasm WASMにコンパイルされたDuckDB はい、カラム型かつベクトル化 クライアントまたはNodeでの本格分析SQL
Apache Arrow (JS) + Arquero カラム型形式 + dplyr風の変換 形式ははい、クエリエンジンはいいえ SQLなしのJS変換パイプライン
Perspective WASMのピボットエンジン(FINOS) はい、対話的集計向け ピボット付きリアルタイムダッシュボード
SQL.js WASMにコンパイルされたSQLite いいえ(行指向) 小さな分析、クライアント上の単純なSQL
TinyBase 軽量なリアクティブストア いいえ アプリ状態に対する単純な集計

選び方

バックエンドなしで、それなりのサイズのParquetやCSVに本物のSQLをかけたいなら、迷わずDuckDB-Wasmです。

すでにArrow形式でデータを扱っていて、SQLを書くよりJavaScriptで変換をチェーンしたいなら:Arquero

ライブで変わるデータをユーザーがピボットする対話的ダッシュボードを作っているなら:Perspective

データセットが小さく、カラム型性能を気にせず基本的なSQLだけ欲しいなら:SQL.js

アプリ状態の中のリアクティブなカウンタや合計だけが必要なら:TinyBase。おそらくOLAPという言葉で考える必要すらありません。

いずれの場合も、本番コードを書く前に、インストールする版の公式ドキュメントを確認してください。初期化API(特にワーカーとWebAssemblyバンドルに依存するDuckDB-WasmとPerspective)は、バージョン間でかなり頻繁に変わります。

よくある質問

WebAssemblyなしの、JavaScriptネイティブなカラム型OLAPエンジンはありますか?

DuckDBやClickHouseに匹敵するものはありません。本物のベクトル化カラム型エンジンはC++やRustで書かれ、WebAssemblyにコンパイルされてJavaScriptに届きます(DuckDB-Wasm、Perspective)。同等の採用を持つこの種のエンジンは、純粋なJavaScriptにはありません。

DuckDB-Wasmはブラウザだけでなく、Nodeのバックエンドでも使えますか?

はい。DuckDB-WasmはブラウザでもNodeでも動きます。ただし純粋なバックエンド向けには、WebAssembly層を避けられるDuckDBのネイティブNodeバインディングもあります。どちらがよいかは、クライアントとサーバーでコードを共有する必要があるかによります。

SQL.jsは本物のOLAPデータベースの代わりになりますか?

大きな負荷にはなりません。SQL.jsは行指向のSQLiteです。クライアント上の小さな分析には向きますが、何百万行のデータセットではカラム型エンジンのようにスケールしません。

Arqueroは動かすのにApache Arrowが必要ですか?

通常の配列に対する基本的な使い方では不要です。Arrowが効いてくるのは、すでにその形式で来るデータ(たとえばDuckDB-Wasmから)と相互運用したいときや、結果をArrowへ書き出したいときです。

関連記事

興味を持ちそうな関連コンテンツを探し続けましょう

提携

私が毎日使っていて、このコミュニティがより良い条件で使えるツールです。

アフィリエイトリンクです。あなたの支払う価格は変わりません。すべての提携を見る
トレーニングプログラム

アイデアを実際のプロジェクトに変える準備はできましたか?

Transformaは、明確さと方法論でプロジェクトを作成・実行・スケールさせることを学ぶプログラムです。

Transformaプログラムを知る