POC開始前に
この文書では、新しいユーザーが遭遇する可能性のある一般的な問題を取り上げ、POCプロセスの促進を目的としています。内容は典型的なPOCワークフローに沿って整理されています:
- テーブル設計 — データモデル、ソートキー、パーティショニング、およびバケッティング戦略を選択します。
- データロード — 適切なロード方法を選択し、一般的な落とし穴を回避します。
- クエリチューニング — 遅いクエリを診断し、バケッティングとインデックス設定を最適化します。
- Data Lakeクエリ — Lakehouseシナリオでの追加最適化のヒントです。
テーブル設計
Dorisでテーブルを作成する際は、ロードとクエリパフォーマンスに影響する4つの決定事項があります:データモデル、ソートキー、パーティショニング、バケッティングです。
データモデル
データの書き込み方法に基づいてモデルを選択してください:
| データ特性 | 推奨モデル | 理由 |
|---|---|---|
| 追記のみ(ログ、イベント、ファクト) | Duplicate Key(デフォルト) | すべての行を保持、最高のクエリパフォーマンス |
| 主キーによる更新(CDC、upsert) | Unique Key | 新しい行が同じキーを持つ古い行を置き換える |
| 事前集計されたメトリクス(PV、UV、合計) | Aggregate Key | 行は書き込み時にSUM/MAX/MINでマージされる |
Duplicate Keyはほとんどのシナリオで機能します。 Data Model Overviewを参照してください。
ソートキー
Dorisはキー列の最初の36バイトにprefix indexを構築します。ソートキーを設定する際は以下の原則に従ってください:
- 頻繁にフィルタされる列を最初に:WHERE条件で最も一般的に使用される列を前に配置します。
- 固定サイズ型を最初に:prefix indexは最初のVARCHAR列で停止するため、VARCHARの前にINT、BIGINT、DATE、その他の固定サイズ型を配置します。
- inverted indexを追加:prefix indexでカバーされない列については、inverted indexesを追加してフィルタリングを高速化します。
パーティショニング
時間列がある場合は、AUTO PARTITION BY RANGE(date_trunc(time_col, 'day'))を使用してpartition pruningを有効にします。Dorisは無関係なパーティションを自動的にスキップします。
バケッティング
デフォルトはRandom bucketing(Duplicate Keyテーブルで推奨)です。特定の列で頻繁にフィルタや結合を行う場合はDISTRIBUTED BY HASH(col)を使用してください。Data Bucketingを参照してください。
バケット数の選択方法:
| 原則 | 詳細 |
|---|---|
| BE数の倍数 | データ分散の均等性を保証します。後でBEが追加された場合、クエリは通常複数のパーティションをスキャンするため、パフォーマンスが維持されます |
| 可能な限り低く | 小さなファイルの生成を回避します |
| バケットあたりの圧縮データ ≤ 20 GB | Unique Keyテーブルでは ≤ 10 GB。SHOW TABLETS FROM your_tableで確認します |
| パーティションあたり128以下 | より多く必要な場合は、まずパーティションを追加することを検討してください。極端な場合の上限は1024ですが、本番環境で必要になることは稀です |
サンプルテンプレート
ログ / イベント分析
CREATE TABLE app_logs
(
log_time DATETIME NOT NULL,
log_level VARCHAR(10),
service_name VARCHAR(50),
trace_id VARCHAR(64),
message STRING,
INDEX idx_message (message) USING INVERTED PROPERTIES("parser" = "unicode")
)
AUTO PARTITION BY RANGE(date_trunc(`log_time`, 'day'))
()
DISTRIBUTED BY RANDOM BUCKETS 10;
Upsert (CDC) を使用したリアルタイムダッシュボード
CREATE TABLE user_profiles
(
user_id BIGINT NOT NULL,
username VARCHAR(50),
email VARCHAR(100),
status TINYINT,
updated_at DATETIME
)
UNIQUE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 10;
メトリクス集約
CREATE TABLE site_metrics
(
dt DATE NOT NULL,
site_id INT NOT NULL,
pv BIGINT SUM DEFAULT '0',
uv BIGINT MAX DEFAULT '0'
)
AGGREGATE KEY(dt, site_id)
AUTO PARTITION BY RANGE(date_trunc(`dt`, 'day'))
()
DISTRIBUTED BY HASH(site_id) BUCKETS 10;
データ読み込み
適切な読み込み方法を選択し、一般的なパフォーマンスの問題を回避するために以下のベストプラクティスに従ってください:
- バルクデータには
INSERT INTO VALUESを使用しないでください。 代わりにStream LoadまたはBroker Loadを使用してください。Loading Overviewを参照してください。 - クライアント側でバッチ書き込みを行ってください。 高頻度の小さなインポートはバージョンの蓄積を引き起こします。実行不可能な場合は、Group Commitを使用してください。
- 大きなインポートを小さなバッチに分割してください。 失敗した長時間実行されるインポートは最初から再開する必要があります。増分インポートにはINSERT INTO SELECT with S3 TVFを使用してください。
- Random bucketingを使用するDuplicate Keyテーブルには
load_to_single_tabletを有効にして 書き込み増幅を削減してください。
Load Best Practicesを参照してください。
クエリチューニング
Bucketing
バケット数はクエリの並列性とスケジューリングオーバーヘッドに直接影響します — この2つのバランスを取ってください:
- 過度にバケット化しないでください。 小さすぎるタブレットが多すぎるとスケジューリングオーバーヘッドが発生し、クエリパフォーマンスが最大50%低下する可能性があります。
- バケット化が不足しないようにしてください。 タブレットが少なすぎるとCPUの並列性が制限されます。
- データスキューを避けてください。
SHOW TABLETSでタブレットサイズを確認してください。サイズが大幅に異なる場合は、Random bucketingまたはより高いカーディナリティのバケット列に切り替えてください。
サイジングガイドラインについてはBucketingを参照してください。
インデックス
- ソートキーに適切な列を配置してください。 PostgreSQLなどのシステムとは異なり、Dorisはキー列の最初の36バイトのみをインデックス化し、最初のVARCHARで停止します。このプレフィックスを超える列はソートキーの恩恵を受けません。これらの列にはinverted indexesを追加してください。Sort Keyを参照してください。
診断ツール
低速クエリの診断についてはQuery Profileを参照してください。
データレイククエリ
POCでDorisを通じてHive、Iceberg、Paimon、または他のデータレイクのデータにクエリを実行する場合(つまり、Lakehouseシナリオ)、以下のポイントがテスト結果に最も大きな影響を与えます。
パーティションプルーニングが効果的であることを確認する
レイクテーブルはしばしば大量のデータを保持しています。DorisNecessary部分のみをスキャンするように、WHERE条件には常にパーティション列を含めてください。EXPLAIN <SQL>を使用してpartitionフィールドを確認し、プルーニングが機能していることを検証してください:
0:VPAIMON_SCAN_NODE(88)
partition=203/0 -- 203 partitions pruned, 0 actually scanned
パーティション数が予想よりもはるかに多い場合は、WHERE条件がパーティション列と正しく一致しているかを確認してください。
Data Cacheの有効化
リモートストレージ(HDFS/object storage)は、ローカルディスクよりもIOレイテンシが大幅に高くなります。Data Cacheは、最近アクセスしたリモートデータをBEのローカルディスクにキャッシュし、同じデータセットに対する繰り返しクエリで内部テーブル並みのクエリパフォーマンスを提供します。
- Cacheはデフォルトで無効になっています。設定と有効化についてはData Cacheのドキュメントを参照してください。
- バージョン4.0.2以降、cache warmupがサポートされており、POCテスト前にホットデータを事前に読み込むことができます。
POC中は、クエリを一度実行してキャッシュを生成し、2回目のクエリのレイテンシをベンチマークとして使用してください。これにより、定常状態の本番パフォーマンスをより正確に反映できます。
小さなファイルへの対処
Data lakeストレージには、多数の小さなファイルが含まれていることがよくあります。小さなファイルは多くのsplitに分割され、FEのメモリ圧迫(OOMの原因となる可能性)を増加させ、クエリ計画のオーバーヘッドを高めます。
- ソースでの修正(推奨): Hive/Spark側で小さなファイルを定期的にコンパクト化し、各ファイルを128 MB以上に保つ。
- Doris側のセーフガード:
SET max_file_split_num = 50000;(4.0.4以降でサポート)を使用して、スキャンあたりの最大split数を制限し、OOMを防ぐ。
診断のためのQuery Profileの使用
Data lakeクエリのボトルネックは、通常計算ではなくIOです。Query Profileは、低速クエリの根本原因の特定に役立ちます。以下に注目してください:
- Split数とデータ量: スキャンされているデータが多すぎるかどうかを判断します。
- MergeIOメトリクス:
MergedBytesがRequestBytesよりもはるかに大きい場合、読み取り増幅が深刻です。merge_io_read_slice_size_bytes(デフォルト8 MB)を削減して軽減してください。 - Cacheヒット率: Data Cacheが効果的に機能していることを確認します。
その他の最適化技術については、Data Lake Query Optimizationを参照してください。