mcpField
D
doris-best-practices

doris-best-practices

github.com/apache数据与数据库47119 次安装4 周前更新
代码仓库

关于 doris-best-practices

doris-best-practices 是指导 Apache Doris 表设计、查询排查和集群 sizing 的技能。它按工作负载整理规则与模板,并提供 DDL 限制及基于证据的运行时诊断指引。

主要功能

  1. 01按工作负载分类的表设计模板
  2. 02CREATE TABLE 前检查清单
  3. 03DDL 限制与常见问题
  4. 04基于证据的查询诊断指引
  5. 05FE、BE 与存储 sizing 指南

适用场景

  1. 01为日志、CDC 或仪表盘设计表
  2. 02选择键、分区、分桶和索引
  3. 03使用 profile 和 EXPLAIN 排查慢查询
  4. 04估算集群与存储需求

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/apache/doris-skills --skill doris-best-practices

安装后在 Claude Code 中输入/doris-best-practices确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
cli-investigation.md
schema-bucket-cloud-mandatory-hash.md
schema-bucket-composite-for-skew.md
schema-bucket-hash-vs-random.md
schema-bucket-high-cardinality-key.md
schema-bucket-target-size.md
schema-cache-file-cache.md
schema-cache-query-partition.md
schema-ddl-gotchas.md
schema-index-bitmap.md
schema-index-bloomfilter.md
schema-index-inverted.md
schema-index-ngram-for-like.md
schema-index-text-search.md
schema-index-vector.md
schema-keys-avoid-float.md
schema-keys-cluster-key-for-mow.md
schema-keys-fixed-length-types.md
schema-keys-prefix-index-limits.md
schema-keys-selectivity-first.md
schema-model-avoid-agg-for-updates.md
schema-model-choose-for-workload.md
schema-model-prefer-mow.md
schema-model-sequence-col-for-cdc.md
schema-mv-async-join.md
schema-mv-async-limits.md
schema-mv-sync-rollup.md
schema-partition-auto-on-demand.md
schema-partition-dynamic-ttl.md
schema-partition-range-for-timeseries.md

详细介绍

Apache Doris 最佳实践

面向问题的 Apache Doris 表设计指南。 37 条规则、7 个用例模板、4 份容量规划指南。 所有详细信息都在 references/ 目录中。


1 ▸ 面向问题的路由

我需要构建……
问题模板关键规则
实时日志/事件分析usecase-log-eventDUPLICATE、RANGE 分区、动态 TTL、ZSTD
CDC/将 MySQL 同步到 Dorisusecase-cdc-syncUNIQUE MoW、sequence_col、HASH 分桶
使用预聚合指标的仪表板usecase-dashboard-metricsAGGREGATE、BITMAP_UNION、同步 MV
面向用户、低延迟点查询的 APIusecase-point-queryUNIQUE MoW、store_row_column、BloomFilter
JOIN 密集型分析的星型模式usecase-star-schema-joinColocation、相同的分桶键/数量
小型维度表/查找表usecase-dimension-lookupDUPLICATE、RANDOM 分桶、3 个桶
可观测性(日志 + 追踪 + 指标)usecase-observability3 张表:DUP 日志、DUP 追踪、AGG 指标
车辆/车队追踪usecase-log-event + usecase-point-query时序 + 点查询混合模式
电商订单分析usecase-star-schema-join + usecase-dashboard-metrics星型模式 + AGG 汇总
全文搜索/内容搜索schema-index-text-search倒排索引、MATCH、BM25
用户行为/漏斗分析schema-types-bitmap-count-distinctBITMAP_UNION、bitmap_intersect
半结构化 JSON 数据schema-types-variant-jsonVARIANT 类型、schema_template
有证据表明我的查询较慢……

对于实时慢查询或运行时诊断,不要首先使用此表。请先阅读 references/cli-investigation.md,并收集或尝试获取证据(profile get、profile list、profile history、tablet、EXPLAIN 或 auth status)。仅在证据指向相应症状后才使用此表。

症状检查这些规则快速修复
WHERE 条件导致全表扫描schema-keys-selectivity-first将过滤列移至排序键第 1 位
JOIN 较慢/发生数据 Shuffleusecase-star-schema-join小型维度表(<1GB):广播 + 运行时过滤。大型维度表:Colocation
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-compressionAUTO PARTITION + ZSTD 压缩 + 定时 DROP PARTITION
未使用同步 MVschema-mv-sync-rollup在 MV GROUP BY 中使用原始列(而不是 date_trunc);使用唯一别名
异步 MV 改写失败schema-mv-async-join + schema-mv-async-limits检查 State/RefreshState;若谓词不匹配,则直接查询 MV
数据倾斜/热点 tabletschema-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。使用 DECIMAL,而非 FLOAT。→ 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')) ()——仅写列名会失败,缺少 () 也会失败
    • 动态分区要求在 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

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 + 行存储)
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 二进制文件是否可用:

  1. 检查 DORIS_CLI_PATH 环境变量——如果已设置,则使用该二进制文件路径
  2. 执行 command -v doriscli——使用 PATH 中的版本
  3. 如果均不可用:回退到 mysql 客户端(参见 references/start-*.md)
如果 doriscli 可用,所有操作优先使用它:
任务doriscli 命令
运行 SQLdoriscli sql "SELECT ..."
检查 DDLdoriscli sql "SHOW CREATE TABLE db.t"
表/tablet 健康状态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。

  • 必须先收集证据:在形成假设之前,先收集或尝试收集性能分析、tablet、DDL、统计信息、EXPLAIN、历史记录、活动查询或连接方面的证据。如果无法在本地收集证据,请说明这一点并提供要运行的确切命令
  • 优先使用现有性能分析:重新执行 SQL 之前,先使用 profile get <query_id>、profile list 或 profile history
  • 主动发现:对于描述模糊的慢查询问题,先运行 auth status、profile list --active 和近期的 profile list,再向用户询问更多背景信息
  • 安全检查:使用 --profile 运行用户 SQL 之前,请检查其安全性(不包含 DDL、不执行数据变更、不进行无界扫描)。对于未知、高峰时段或开销较大的 SQL,请先运行 doriscli sql "EXPLAIN <query>" --format json,然后征求确认或请求现有的 query_id
  • 提供假设,而非定论:诊断对应关系是启发式的。请说明证据、可能的原因、下一步需要检查的内容,以及结论可能不成立的情况
  • 如果 doriscli 不可用,请回退到参考文档中列出的 SQL 命令
  • 结构化且便于 Agent 读取的输出一律使用 --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 使用 Sequence 列
分区策略 — 关键(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 时跳过分区
分桶策略 — 严重(5 条规则)
  • schema-bucket-hash-vs-random — 使用 HASH 进行裁剪,仅对 DUP 使用 RANDOM
  • schema-bucket-high-cardinality-key — 选择高基数列
  • schema-bucket-composite-for-skew — 使用复合键解决数据倾斜
  • schema-bucket-target-size — 每个 tablet 的目标大小为 1-10 GB
  • schema-bucket-cloud-mandatory-hash — Cloud MoW 必须使用 HASH
排序键 — 严重(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
数据类型 — 高(5 条规则)
  • schema-types-native-vs-string — 使用原生类型,而非 STRING
  • schema-types-zonemap-limitations — JSON/ARRAY 会禁用 ZoneMap
  • schema-types-variant-json — 使用 VARIANT 存储半结构化 JSON
  • schema-types-bitmap-count-distinct — 使用 BITMAP_UNION 进行精确去重计数
  • schema-types-doris-specifics — DATETIME 精度、VARCHAR 与 STRING 的区别
索引 — 高(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
查询加速 — 高(3 条规则)
  • schema-mv-sync-rollup — 对单表聚合使用同步 MV
  • schema-mv-async-join — 对多表 JOIN 使用异步 MV
  • schema-mv-async-limits — 运行限制(50M 行,3 个并发)
表属性 — 高/中(2 条规则)
  • schema-props-cloud-forced — Cloud 模式强制属性
  • schema-props-compression — LZ4 与 ZSTD 压缩
缓存 — 中(2 条规则)
  • schema-cache-file-cache — Cloud 模式使用文件缓存
  • schema-cache-query-partition — 查询缓存和分区缓存

评论

支持 Markdown