Apache Dorisの導入と活用ガイド:リアルタイムDWHと分析ダッシュボードの構築

Database tutorial - IT technology blog
Database tutorial - IT technology blog

1. クイックスタート:Apache Dorisの立ち上げと5分で始めるデータクエリ

数千万行のデータを1秒未満でスキャンする性能をすぐに検証したい場合、DockerのAll-in-One構成を利用するのが最も手軽な方法です。

以下の設定で docker-compose.yml ファイルを作成します:

version: '3.8'
services:
  doris:
    image: apache/doris:doris-all-in-one-2.1.0
    container_name: apache-doris-standalone
    ports:
      - "8030:8030"   # FE HTTP Server
      - "9030:9030"   # FE MySQL Server Port
      - "8040:8040"   # BE HTTP Server
    environment:
      - FE_SERVERS=fe1:127.0.0.1:9010
      - BE_SERVERS=be1:127.0.0.1:9050
    volumes:
      - doris_fe:/opt/apache-doris/fe/doris-meta
      - doris_be:/opt/apache-doris/be/storage
volumes:
  doris_fe:
  doris_be:

バックグラウンドでコンテナを起動します:

docker compose up -d

Dorisは標準的なMySQLプロトコルに対応しています。使い慣れたMySQLクライアントからそのまま接続できます(デフォルトユーザーは root、パスワードなし):

mysql -h 127.0.0.1 -P 9030 -u root

データベースを作成し、Webアクセスログ分析用のサンプルテーブルを定義します:

CREATE DATABASE analytics_db;
USE analytics_db;

CREATE TABLE site_access_log (
    event_date DATE NOT NULL,
    site_id INT NOT NULL,
    user_id VARCHAR(64) NOT NULL,
    page_url VARCHAR(255),
    pv INT SUM DEFAULT "1"
)
AGGREGATE KEY(event_date, site_id, user_id, page_url)
DISTRIBUTED BY HASH(site_id) BUCKETS 10
PROPERTIES("replication_num" = "1");

INSERT INTO site_access_log VALUES
('2026-03-01', 101, 'usr_9921', '/home', 1),
('2026-03-01', 101, 'usr_9921', '/home', 2),
('2026-03-01', 102, 'usr_1024', '/checkout', 1);

SELECT site_id, SUM(pv) as total_views FROM site_access_log GROUP BY site_id;

2. 詳細解説:従来のRDBMSのボトルネックとDorisのMPPアーキテクチャ

分析処理において従来のRDBMSが限界を迎える理由

MySQLやPostgreSQL上の orders や tracking_logs テーブルが500万件から8000万件へと肥大化した場合を想像してみてください。この規模になると、GROUP BY を伴う SUM 集計や COUNT(DISTINCT user_id) を実行するだけでディスクI/Oが逼迫し、サーバーのCPU使用率は100%に達します。その結果、MetabaseやGrafanaなどのダッシュボードは30〜40秒以上も応答待ちのままローディングが回り続けることになります。

この問題の根本的な原因は、行指向(Row-oriented)のストレージ構造にあります。たとえ order_date と amount の2列だけを集計したい場合でも、データベースは shipping_address やJSONペイロードなどの容量の大きい列を含む行全体をディスクから読み出してRAMにロードせざるを得ません。

Apache Dorisはどのようにこの課題を解決するのか?

Dorisは、大規模並列処理(MPP: Massively Parallel Processing)アーキテクチャを採用したモダンなデータウェアハウス(DWH)です。列指向ストレージ(Columnar Storage)とベクトル化実行エンジン(SIMD)を組み合わせることで、クエリ応答時間を1秒未満(サブセカンド)に抑え込みます。

  • 列指向ストレージと高効率な圧縮: Dorisはクエリで指定された列のみを読み取ります。LZ4やZSTDアルゴリズムによる圧縮により、実環境で5:1〜8:1の圧縮率を達成し、ディスク容量を最大75%削減します。
  • 2つのコンポーネントのみで構成されるシンプル設計: DorisクラスタはFrontend(FE:メタデータ管理、SQLパース、実行プラン配信)とBackend(BE:タブレットの保持、分散スキャンおよび計算)のみで構成されます。ZooKeeperやHadoop HDFSに依存せず完全に自己完結して動作するため、運用負担を大幅に軽減できます。
  • MySQL Wireプロトコルとの完全な互換性: サードパーティ製のドライバを追加することなく、Superset、Metabase、Tableau、PowerBIなどの主要なBIツールをDorisに直接接続できます。

3. 応用編:データモデルの設計とリアルタイムなStream Load

ユースケースに応じたデータモデルの選定

Dorisでは、用途に応じて以下の3つのコアなテーブルモデルが提供されています:

  1. Aggregate Model(集約モデル): 書き込み時に指定キーに基づいて自動的にデータを事前集約します(ダッシュボードの指標やPV/UV集計に最適)。
  2. Unique Key Model(ユニークキーモデル): 高速なUpsert/Deleteをサポートします(MySQLやPostgreSQLからのリアルタイムCDC同期に最適)。
  3. Duplicate Model(重複モデル): 生のログデータをそのまま保持し、ソートプレフィックスインデックスを活用して特定範囲の高速スキャンを実現します。

以下は、頻繁な更新処理に最適化されたMerge-on-Write機能を有効にしたUnique Modelテーブルの作成例です:

CREATE TABLE ecom_orders (
    order_id BIGINT NOT NULL,
    user_id INT NOT NULL,
    order_status VARCHAR(32),
    total_amount DECIMAL(12, 2),
    updated_at DATETIME
)
UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 16
PROPERTIES(
    "enable_unique_key_merge_on_write" = "true",
    "replication_num" = "1"
);

Pythonを使用したHTTP Stream Loadによるデータ投入

DorisにはHTTP Stream Loadプロトコルが標準で組み込まれており、JSONやCSV形式のマイクロバッチデータをターゲットテーブルに直接投入できます。単一のBEノードでも毎秒30,000〜50,000レコードのスループットを発揮します。

Stream Loadを使用してリアルタイムにデータを投入するPythonスクリプトの例:

import requests
import json

doris_host = "http://127.0.0.1:8030"
db = "analytics_db"
table = "ecom_orders"
url = f"{doris_host}/api/{db}/{table}/_stream_load"

headers = {
    "format": "json",
    "strip_outer_array": "true",
    "Expect": "100-continue"
}

data = [
    {"order_id": 10001, "user_id": 55, "order_status": "PAID", "total_amount": 1450000.00, "updated_at": "2026-03-01 10:20:00"},
    {"order_id": 10002, "user_id": 89, "order_status": "SHIPPED", "total_amount": 320000.00, "updated_at": "2026-03-01 10:21:15"}
]

response = requests.put(
    url,
    data=json.dumps(data),
    headers=headers,
    auth=("root", "")
)

print(response.json())

4. 本番環境(Production)運用の実践ノウハウ

私たちのチームのトラッキングシステムが月間2億5000万レコードに達した際、レポーティング処理のワークロード全体をApache Dorisに移行したことで、メインのMySQLクラスタのCPU負荷を最大75%削減できました。以下に、本番運用で留意すべき4つの実践ノウハウを紹介します:

  • 適切なバケット数の設定: 1つのタブレット(圧縮後のバケット)の理想的なサイズは100MB〜1GB程度です。わずか200万行のテーブルに対して100バケットを設定するような過剰な細分化は、メタデータの断片化を引き起こしFEの管理負荷を増大させるため避けてください。
  • Rollup Indexの活用: 明細テーブルに秒単位でログを保持していても、レポート用途では日次集約がメインとなるケースが多くあります。バックグラウンドでRollup Indexを作成しておくことで、元のSQLクエリを変更することなく、トレンドグラフの描画クエリ速度を5〜10倍高速化できます。
  • Backend(BE)ハードウェアの選定: ストレージにはNVMe SSDを採用することをおすすめします。また、Dorisはベクトル計算にSIMD命令セット(AVX2/AVX-512)をフル活用するため、コア数が多くクロックが低いCPUよりも、シングルコアの動作周波数が高いCPU(3.2GHz以上)を選定した方が劇的な性能向上が得られます。
  • FEのヒープメモリ設定: DorisのメタデータはFEのメモリ(RAM)上にすべて保持されます。パーティション数が数億規模に達する場合は、OutOfMemoryエラーを防ぐためにJVMヒープサイズとして最低8GB〜16GB(conf/fe.conf 内のパラメータ JAVA_OPTS="-Xmx8192m" など)を割り当ててください。
Share: