doris-best-practices について
doris-best-practicesは、Apache Dorisのテーブル設計、クエリ調査、クラスター容量設計を支援するスキルです。ワークロード別のルールやテンプレートに加え、DDL制約と証拠に基づく診断手順をまとめています。
主な機能
- 01ワークロード別のテーブル設計テンプレート
- 02CREATE TABLE前のチェックリスト
- 03DDLの制約と注意点
- 04証拠に基づくクエリ診断手順
- 05FE、BE、ストレージの容量設計ガイド
活用シーン
- 01ログ、CDC、ダッシュボード向けテーブル設計
- 02キー、パーティション、バケット、インデックスの選択
- 03profileやEXPLAINによる低速クエリの調査
- 04クラスターとストレージの容量見積もり
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ apache/ doris-skills --skill doris-best-practicesインストール後、Claude Code で/doris-best-practicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/cli-investigation.mdschema-bucket-cloud-mandatory-hash.mdschema-bucket-composite-for-skew.mdschema-bucket-hash-vs-random.mdschema-bucket-high-cardinality-key.mdschema-bucket-target-size.mdschema-cache-file-cache.mdschema-cache-query-partition.mdschema-ddl-gotchas.mdschema-index-bitmap.mdschema-index-bloomfilter.mdschema-index-inverted.mdschema-index-ngram-for-like.mdschema-index-text-search.mdschema-index-vector.mdschema-keys-avoid-float.mdschema-keys-cluster-key-for-mow.mdschema-keys-fixed-length-types.mdschema-keys-prefix-index-limits.mdschema-keys-selectivity-first.mdschema-model-avoid-agg-for-updates.mdschema-model-choose-for-workload.mdschema-model-prefer-mow.mdschema-model-sequence-col-for-cdc.mdschema-mv-async-join.mdschema-mv-async-limits.mdschema-mv-sync-rollup.mdschema-partition-auto-on-demand.mdschema-partition-dynamic-ttl.mdschema-partition-range-for-timeseries.md詳細
Apache Doris のベストプラクティス
Apache Doris 向けの、課題起点のテーブル設計インテリジェンスです。 37 個のルール、7 個のユースケーステンプレート、4 個のサイジングガイドを収録しています。 詳細はすべて
references/ディレクトリにあります。
1 ▸ 課題起点のルーティング
構築したいもの…
| 課題 | テンプレート | 主なルール |
|---|---|---|
| リアルタイムのログ/イベント分析 | usecase-log-event | DUPLICATE、RANGE パーティション、動的 TTL、ZSTD |
| CDC/MySQL から Doris への同期 | usecase-cdc-sync | UNIQUE MoW、sequence_col、HASH バケット |
| 事前集計済みメトリクスを使うダッシュボード | usecase-dashboard-metrics | AGGREGATE、BITMAP_UNION、同期 MV |
| 低レイテンシのポイントクエリを使うユーザー向け API | usecase-point-query | UNIQUE MoW、store_row_column、BloomFilter |
| JOIN を多用する分析向けのスター・スキーマ | usecase-star-schema-join | コロケーション、同じバケットキー/数 |
| 小規模なディメンション/ルックアップテーブル | usecase-dimension-lookup | DUPLICATE、RANDOM バケット、3 バケット |
| オブザーバビリティ(ログ+トレース+メトリクス) | usecase-observability | 3 つのテーブル:DUP ログ、DUP トレース、AGG メトリクス |
| 車両/フリートのトラッキング | usecase-log-event + usecase-point-query | 時系列とポイントクエリのハイブリッド |
| E コマースの注文分析 | usecase-star-schema-join + usecase-dashboard-metrics | スター・スキーマ+AGG ロールアップ |
| 全文検索/コンテンツ検索 | schema-index-text-search | 転置インデックス、MATCH、BM25 |
| ユーザー行動/ファネル分析 | schema-types-bitmap-count-distinct | BITMAP_UNION、bitmap_intersect |
| 半構造化 JSON データ | schema-types-variant-json | VARIANT 型、schema_template |
証拠から次の状況がわかり、クエリが遅い場合…
実行中のスロークエリやランタイムの診断では、最初の対応としてこの表を使用しないでください。まず references/cli-investigation.md を読み、証拠を収集するか、収集を試みてください(profile get、profile list、profile history、tablet、EXPLAIN、または auth status)。この表は、証拠から症状が特定できた場合にのみ使用してください。
| 症状 | 確認するルール | すぐにできる修正 |
|---|---|---|
| WHERE 句でテーブル全体がスキャンされる | schema-keys-selectivity-first | フィルター対象の列をソートキーの先頭に移動する |
| JOIN が遅い/シャッフルが発生する | usecase-star-schema-join | 小規模なディメンション(<1GB):ブロードキャスト+ランタイムフィルター。大規模な場合:コロケーション |
| COUNT DISTINCT が遅い | schema-types-bitmap-count-distinct | BITMAP_UNION 集計に切り替える |
| LIKE '%keyword%' が遅い | schema-index-ngram-for-like | NGram BloomFilter インデックスを追加する |
| ポイントクエリのレイテンシが高すぎる | usecase-point-query | store_row_column と Prepared Statement を有効にする |
| ストレージの増加が速すぎる | schema-partition-auto-on-demand + schema-props-compression | AUTO PARTITION+ZSTD 圧縮+DROP PARTITION の定期実行 |
| 同期 MV が使用されない | schema-mv-sync-rollup | MV の GROUP BY では date_trunc ではなく生の列を使用する。一意なエイリアスを指定する |
| 非同期 MV の書き換えに失敗する | schema-mv-async-join + schema-mv-async-limits | State/RefreshState を確認する。述語が一致しない場合は MV を直接クエリする |
| データの偏り/ホットタブレット | schema-bucket-composite-for-skew | 複合バケットキーまたは RANDOM を使用する |
| インポート失敗/データバージョンエラー | schema-mv-async-limits | MV の同時リフレッシュ上限(最大 3)を確認する |
| キー内の VARCHAR がパフォーマンスを低下させる | schema-keys-fixed-length-types | VARCHAR を固定長型の後ろに移動する |
| UNIQUE テーブルへの書き込みが遅い | schema-model-prefer-mow | MoW が有効(MoR ではない)ことを確認する |
2 ▸ フライト前チェックリスト(CREATE TABLE の前に必ず確認)
このチェックリストを順番に確認してください。各項目には該当するルールが記載されています。
- データモデル — UNIQUE(更新しますか?)か DUPLICATE(追記しますか?)か AGGREGATE(事前集計のみですか?)→
schema-model-choose-for-workload - パーティション戦略 — 時系列データですか? AUTO PARTITION を推奨します。小さなテーブルですか?省略します。AUTO と dynamic_partition を併用しないでください。→
schema-partition-* - バケットキーと数 — JOIN キーに HASH を使用します。明示的な数を計算します:
daily_GB / target_tablet_GB。ボリュームが不明な場合は、明示的なフォールバック数を使用します:小規模ディメンションは 3、中規模テーブルは 8、大規模な日次ファクトテーブルは 16-32。→schema-bucket-* - ソートキーの順序 — 選択性の高いものを先にし、固定長の列を VARCHAR より前にします →
schema-keys-* - データ型 — STRING ではなくネイティブ型を使用します。FLOAT ではなく DECIMAL を使用します。→
schema-types-* - インデックス — 等価検索には BloomFilter、テキストには Inverted、LIKE には NGram を使用します →
schema-index-* - プロパティ — MoW は有効ですか?圧縮は設定されていますか?クラウドモードの replication_num=1 は設定されていますか?→
schema-props-* - DDL の厳格な制約(いずれかに違反すると Apache Doris は DDL を拒否します):
- UNIQUE KEY + PARTITION BY RANGE の場合、パーティション列は UNIQUE KEY に必ず含める必要があります:
UNIQUE KEY(id, dt) PARTITION BY RANGE(dt) - キー列はスキーマの最初の N 列で、同じ順序でなければなりません。キー列を先に、非キー列を後に配置します。例:
UNIQUE KEY(account_id, symbol)の場合、スキーマはaccount_id, symbol, ...で始める必要があります。キー列の間に非キー列を配置しないでください store_row_column = "true"は UNIQUE MoW と DUPLICATE で動作しますが、AGGREGATE では動作しません(Doris は AGG を拒否します:「Aggregate table can't support row column」)。4.x で確認済みです。旧バージョンでは UNIQUE のみ対応していました- AUTO PARTITION には
date_trunc()と空のかっこが必要です:AUTO PARTITION BY RANGE(date_trunc(col, 'day')) ()— 列名のみでは失敗し、()がない場合も失敗します - Dynamic partition には、DDL に明示的な
PARTITION BY RANGE(col) ()句が必要です。プロパティだけでは不十分です dynamic_partition.bucketsは設定しないでください。数値はDISTRIBUTED BY HASH(col) BUCKETS Nにのみ指定しますcompaction_policy = "time_series"は DUPLICATE テーブルでのみ使用できます。UNIQUE では失敗します- 非同期 MV 更新には、
REFRESH AUTO ON SCHEDULE EVERY 10 MINUTEまたはREFRESH COMPLETE ON SCHEDULE EVERY 10 MINUTEを使用します。REFRESH SCHEDULE EVERYやREFRESH ASYNC EVERY(INTERVAL ...)は使用しないでください。最小間隔は 1 MINUTE です NOW()/CURDATE()を使用する MV では、PROPERTIES ("enable_nondeterministic_function" = "true")を追加します- BOOLEAN のデフォルト値は引用符で囲む必要があります:
DEFAULT "true"。DEFAULT TRUEではありません - BloomFilter インデックスには
PROPERTIES ("bloom_filter_columns" = "col1,col2")を使用します。インラインのINDEX ... USING BLOOM FILTERは使用しないでください - AGGREGATE の列構文では、デフォルト値より前に集計関数を指定します:
col BIGINT SUM DEFAULT "0"。col BIGINT DEFAULT "0" SUMではありません - AGGREGATE の
DEFAULT "null"は VARCHAR でのみ動作します。INT、DATE、DECIMAL、BIGINT では失敗します。文字列以外の型で REPLACE_IF_NOT_NULL を使用する場合は、DEFAULT を完全に省略します:vip_level INT REPLACE_IF_NOT_NULL(DEFAULT "null"は指定しません) enable_unique_key_partial_updateはセッション変数であり、テーブルプロパティではありません- 詳細:
schema-ddl-gotchas
- UNIQUE KEY + PARTITION BY RANGE の場合、パーティション列は UNIQUE KEY に必ず含める必要があります:
2b ▸ DDL テンプレート(最も近いものをコピーし、列をカスタマイズ)
CREATE TABLE ごとに、以下から最も近いテンプレートを選択してください。列名、型、バケット数、パーティション設定をカスタマイズします。DDL を一から記述しないでください。
T1: 追記専用イベント/ログ(DUPLICATE)
CREATE TABLE events (
entity_id VARCHAR(64) NOT NULL,
event_time DATETIME NOT NULL,
event_type VARCHAR(50) NOT NULL,
payload VARIANT
) DUPLICATE KEY(entity_id, event_time, event_type)
PARTITION BY RANGE(event_time) ()
DISTRIBUTED BY HASH(entity_id) BUCKETS 10
PROPERTIES (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-90",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"compression" = "zstd",
"compaction_policy" = "time_series",
"replication_num" = "1"
);
T2: パーティション付きの更新可能なデータ(UNIQUE MoW + CDC)
CREATE TABLE orders (
order_id BIGINT NOT NULL,
order_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
status VARCHAR(20),
amount DECIMAL(18,2)
) UNIQUE KEY(order_id, order_time)
PARTITION BY RANGE(order_time) ()
DISTRIBUTED BY HASH(order_id) BUCKETS 5
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"function_column.sequence_col" = "update_time",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-365",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"replication_num" = "1"
);
T3: 小規模ディメンション/ルックアップ(UNIQUE、パーティションなし)
CREATE TABLE dim_product (
product_id INT NOT NULL,
name VARCHAR(200),
category VARCHAR(50)
) UNIQUE KEY(product_id)
DISTRIBUTED BY HASH(product_id) BUCKETS 3
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"replication_num" = "1"
);
T4: 事前集計済み KPI(AGGREGATE)
CREATE TABLE daily_kpi (
stat_date DATE NOT NULL,
dimension VARCHAR(50) NOT NULL,
metric_sum BIGINT SUM DEFAULT "0",
metric_max DOUBLE MAX DEFAULT "0",
unique_users BITMAP BITMAP_UNION
) AGGREGATE KEY(stat_date, dimension)
PARTITION BY RANGE(stat_date) ()
DISTRIBUTED BY HASH(dimension) BUCKETS 3
PROPERTIES (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "MONTH",
"dynamic_partition.start" = "-12",
"dynamic_partition.end" = "1",
"dynamic_partition.prefix" = "p",
"replication_num" = "1"
);
T5: ポイントクエリ/API サービング(UNIQUE MoW + row store)
CREATE TABLE user_profiles (
user_id BIGINT NOT NULL,
update_time DATETIME NOT NULL,
name VARCHAR(100),
data VARIANT
) UNIQUE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 5
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"function_column.sequence_col" = "update_time",
"store_row_column" = "true",
"light_schema_change" = "true",
"replication_num" = "1"
);
3 ▸ 接続と CLI
Apache Doris は MySQL プロトコルに対応しているため、常に利用可能な方法として、MySQL 互換クライアント(mysql)と SQL、FE HTTP REST API を使用できます。一部のディストリビューションには、プロファイリングや診断用の便利なコマンドを追加するオプションの管理 CLI(ここでは doriscli と呼びます)も含まれています。ディストリビューションで提供されている場合はこれを使用し、提供されていない場合はネイティブの方法を使用してください。
オプションの CLI を検出する
クエリを実行する前に、CLI バイナリが利用可能かどうかを検出してください。
DORIS_CLI_PATH環境変数を確認します。設定されている場合は、そのバイナリパスを使用しますcommand -v doriscliを実行します。PATH 上にあるものを使用します- どちらも利用できない場合は、
mysqlクライアントにフォールバックします(references/start-*.mdを参照)
doriscli が利用可能な場合は、すべての操作で優先して使用してください。
| タスク | doriscli コマンド |
|---|---|
| SQL の実行 | doriscli sql "SELECT ..." |
| DDL の確認 | doriscli sql "SHOW CREATE TABLE db.t" |
| テーブル/タブレットの健全性確認 | doriscli tablet db.t(概要)または doriscli tablet db.t --detail |
| 遅いクエリのプロファイリング | doriscli sql "SELECT ..." --profile → query_id を取得 |
| クエリプロファイルの取得 | doriscli profile get <qid>、または完全な診断には --full |
| 高速クエリと低速クエリの比較 | doriscli profile diff <slow_qid> <fast_qid> |
| パフォーマンスの推移 | doriscli profile history <sql_pattern> --days 7 |
| 接続のテスト | doriscli auth status |
| 環境の切り替え | doriscli use <name> |
実行時のクエリ調査
遅いクエリや実行時のパフォーマンス問題については、references/cli-investigation.md を読んでください。
- 証拠の収集が必須です:仮説を立てる前に、プロファイル、タブレット、DDL、統計情報、EXPLAIN、履歴、実行中のクエリ、または接続の証拠を収集するか、収集を試みてください。ローカルで証拠を収集できない場合は、その旨を伝え、実行する正確なコマンドを提示してください
- 既存のプロファイルを優先してください:SQL を再実行する前に、
profile get <query_id>、profile list、またはprofile historyを使用してください - 積極的に情報を確認してください:遅いクエリについて曖昧な報告を受けた場合は、ユーザーに詳細を尋ねる前に、
auth status、profile list --active、および最近のprofile listから開始してください - 安全性の確認:ユーザーの SQL を
--profile付きで実行する前に、安全かどうかを確認してください(DDL がなく、データ変更がなく、範囲に制限のないスキャンでないこと)。SQL が不明な場合、ピーク時間帯の場合、または負荷が高い場合は、まずdoriscli sql "EXPLAIN <query>" --format jsonを実行し、確認を求めるか既存の query_id を提示してもらってください - 断定ではなく仮説を示してください:診断上の対応付けはヒューリスティックです。証拠、考えられる原因、次に確認すべき点、結論が誤っている可能性がある状況を提示してください
- doriscli が利用できない場合は、リファレンスに記載された SQL コマンドにフォールバックしてください
- 構造化されたエージェント可読形式の出力には、必ず
--format jsonを使用してください
クイックスタートガイド
references/start-self-hosted.md— セルフホスト/BYOC/オンプレミス- クラウドモード(ストレージとコンピュート)では HTTP ポート(8080 と 8030)が異なるだけです。同じガイドを使用できます
4 ▸ クラスターのサイジング
サイジングガイド:
references/sizing-fe.md— FE ノードのサイジングreferences/sizing-be-integrated.md— BE のサイジング(統合ストレージ)references/sizing-be-cloud.md— BE のサイジング(クラウド/ストレージとコンピュート)references/sizing-storage-formula.md— ストレージ計算式
5 ▸ カテゴリ別ルールインデックス
データモデル — 重要(4 ルール)
schema-model-choose-for-workload— DUP、UNIQUE、AGG の選択フローチャートschema-model-prefer-mow— UNIQUE テーブルでは常に MoW を使用schema-model-avoid-agg-for-updates— AGG では UPDATE/DELETE を実行できませんschema-model-sequence-col-for-cdc— 順不同の CDC に使用するシーケンス列
パーティション戦略 — 重要(4 ルール)
schema-partition-range-for-timeseries— 時系列データには RANGE を使用schema-partition-dynamic-ttl— TTL の自動化には動的パーティションを使用schema-partition-auto-on-demand— 断続的なデータには AUTO を使用schema-partition-skip-for-small— 1 GB 未満ではパーティション分割を省略
バケット戦略 — CRITICAL(5 つのルール)
schema-bucket-hash-vs-random— プルーニングには HASH、DUP のみに RANDOM を使用しますschema-bucket-high-cardinality-key— カーディナリティの高いカラムを選択しますschema-bucket-composite-for-skew— データの偏りを解消するには複合キーを使用しますschema-bucket-target-size— タブレットあたり 1~10 GB を目標にしますschema-bucket-cloud-mandatory-hash— Cloud MoW では HASH が必須です
ソートキー — CRITICAL(5 つのルール)
schema-keys-selectivity-first— 選択性の高いものを先にしますschema-keys-fixed-length-types— VARCHAR より固定長の型を先にしますschema-keys-prefix-index-limits— 最大 36 バイトで、VARCHAR が終端になりますschema-keys-cluster-key-for-mow— UNIQUE テーブルにはクラスタキーを使用しますschema-keys-avoid-float— ソートキーに FLOAT/DOUBLE を使用しません
データ型 — HIGH(5 つのルール)
schema-types-native-vs-string— STRING ではなく、ネイティブ型を使用しますschema-types-zonemap-limitations— JSON/ARRAY は ZoneMap を無効にしますschema-types-variant-json— 半構造化 JSON には VARIANT を使用しますschema-types-bitmap-count-distinct— 正確な個別値カウントには BITMAP_UNION を使用しますschema-types-doris-specifics— DATETIME の精度、VARCHAR と STRING の違い
インデックス — HIGH(7 つのルール)
schema-index-bloomfilter— 等価比較には BloomFilter を使用しますschema-index-inverted— テキストや範囲検索には転置インデックスを使用しますschema-index-ngram-for-like— LIKE %pattern% には NGram を使用しますschema-index-bitmap— 中程度のカーディナリティには Bitmap を使用しますschema-index-vector— ANN 検索には HNSW/IVF を使用しますschema-index-text-search— 全文検索には MATCH と BM25 を使用します
クエリアクセラレーション — HIGH(3 つのルール)
schema-mv-sync-rollup— 単一テーブルの集計には同期 MV を使用しますschema-mv-async-join— 複数テーブルの JOIN には非同期 MV を使用しますschema-mv-async-limits— 運用上の制限(5000 万行、同時実行 3 件)
テーブルプロパティ — HIGH/MEDIUM(2 つのルール)
schema-props-cloud-forced— Cloud モードで強制されるプロパティschema-props-compression— LZ4 と ZSTD の圧縮
キャッシュ — MEDIUM(2 つのルール)
schema-cache-file-cache— Cloud モードにはファイルキャッシュを使用しますschema-cache-query-partition— クエリキャッシュとパーティションキャッシュ