预计阅读时间: 50 分钟 前置阅读: doc-08, doc-17, doc-21 下一次阅读: doc-23(生产运维与灾备)
1. 为什么 Doris 可以做可观测分析
可观测数据有三个特征:
- 写入量大, 明细多。
- 查询既有时间范围扫描, 又有高选择性过滤。
- 字段变化快, 半结构化内容多。
Doris 的列存、分区分桶、倒排索引、Bitmap/HLL、物化视图和湖仓查询能力, 可以支撑日志、指标、Trace、审计和安全分析等场景。
参考:
- https://doris.apache.org/docs/4.x/observability/overview/
- https://doris.apache.org/docs/4.x/key-features/
- https://doris.apache.org/docs/4.x/table-design/index/inverted-index/overview/
2. 日志明细表设计
日志表通常使用 Duplicate Key:
CREATE TABLE app_log
(
log_time DATETIME NOT NULL,
tenant_id BIGINT NOT NULL,
service_name VARCHAR(64),
level VARCHAR(16),
trace_id VARCHAR(64),
span_id VARCHAR(64),
message STRING,
attrs VARIANT,
INDEX idx_message (message) USING INVERTED PROPERTIES("parser" = "unicode"),
INDEX idx_trace_id (trace_id) USING INVERTED
)
DUPLICATE KEY(log_time, tenant_id, service_name)
AUTO PARTITION BY RANGE(date_trunc(log_time, 'day')) ()
DISTRIBUTED BY HASH(tenant_id) BUCKETS 32
PROPERTIES (
"replication_num" = "3"
);
设计理由:
log_time用于 Partition 和时间裁剪。tenant_id保证多租户查询隔离。service_name是高频过滤和聚合维度。trace_id适合点查。message适合倒排索引。attrs承载变化快的半结构化字段。
3. Trace 表设计
Trace Span 查询通常有两类:
- 根据
trace_id点查整条链路。 - 按服务、接口、状态码、耗时做聚合。
一种设计:
CREATE TABLE trace_span
(
start_time DATETIME NOT NULL,
tenant_id BIGINT NOT NULL,
trace_id VARCHAR(64) NOT NULL,
span_id VARCHAR(64) NOT NULL,
parent_span_id VARCHAR(64),
service_name VARCHAR(64),
operation_name VARCHAR(128),
duration_ms BIGINT,
status_code VARCHAR(32),
attrs VARIANT,
INDEX idx_trace_id (trace_id) USING INVERTED,
INDEX idx_operation (operation_name) USING INVERTED
)
DUPLICATE KEY(start_time, tenant_id, service_name)
AUTO PARTITION BY RANGE(date_trunc(start_time, 'day')) ()
DISTRIBUTED BY HASH(tenant_id) BUCKETS 32;
如果 trace_id 点查是核心路径, 可以考虑单独建设一张按 trace_id 排序或分桶的 Trace 明细表, 不要让一张表同时服务所有访问模式。
4. 指标表设计
指标更适合 Aggregate Key 或 Duplicate Key + 物化视图。
CREATE TABLE metric_minute
(
ts_minute DATETIME NOT NULL,
tenant_id BIGINT NOT NULL,
metric_name VARCHAR(128) NOT NULL,
service_name VARCHAR(64),
tags_hash BIGINT NOT NULL,
value_sum DOUBLE SUM,
value_count BIGINT SUM,
value_max DOUBLE MAX,
value_min DOUBLE MIN
)
AGGREGATE KEY(ts_minute, tenant_id, metric_name, service_name, tags_hash)
AUTO PARTITION BY RANGE(date_trunc(ts_minute, 'day')) ()
DISTRIBUTED BY HASH(tenant_id) BUCKETS 32;
高基数 tags 是指标系统的难点:
- 常用维度拆成显式列。
- 冷门标签放入半结构化字段。
- 对高频查询组合做物化视图。
- 控制标签基数, 不要无限制写入用户 ID、请求 ID。
5. 倒排索引的使用边界
倒排索引适合:
- 日志 message 检索。
- Trace ID / request ID 点查。
- 文本字段 LIKE/全文搜索。
- JSON/VARIANT 子字段搜索。
但倒排索引不是免费的:
- 写入时要构建索引。
- 存储会增加。
- Compaction 成本会上升。
- 查询如果没有选择性, 仍然会慢。
策略:
| 字段 | 索引建议 |
|---|---|
message | Inverted Index + 合适 parser |
trace_id | Inverted 或 Bloom, 取决于查询形态 |
service_name | Sort Key 或 Bitmap |
level/status_code | Bitmap 或作为排序前缀 |
attrs.user_id | 高频点查再建索引 |
6. VARIANT 与半结构化字段
可观测数据经常出现字段漂移:
{
"http.method": "GET",
"http.status_code": 500,
"k8s.pod.name": "checkout-7d9f",
"error.type": "TimeoutException"
}
全部拍平成列会导致宽表膨胀; 全部塞入字符串又无法高效过滤。VARIANT 适合承载变化字段, 但专家要分层:
| 字段类型 | 放哪里 |
|---|---|
| 高频过滤维度 | 独立列 |
| 高频聚合维度 | 独立列 |
| 稳定业务主键 | 独立列或 Key |
| 变化快的标签 | VARIANT |
| 长文本 | STRING + 倒排 |
原则:
- 不要把所有字段都塞进 VARIANT。
- 也不要为每个偶发字段加物理列。
- 高频子字段可以通过 Schema Template 或索引策略稳定下来。
7. 可观测查询模板
错误日志检索
SELECT log_time, service_name, trace_id, message
FROM app_log
WHERE log_time >= now() - INTERVAL 1 HOUR
AND tenant_id = 1001
AND level = 'ERROR'
AND message MATCH 'timeout'
ORDER BY log_time DESC
LIMIT 100;
Trace 聚合
SELECT service_name, operation_name, count(*) AS spans, avg(duration_ms) AS avg_ms
FROM trace_span
WHERE start_time >= now() - INTERVAL 15 MINUTE
AND tenant_id = 1001
GROUP BY service_name, operation_name
ORDER BY avg_ms DESC
LIMIT 50;
指标下钻
SELECT ts_minute, sum(value_sum) / nullif(sum(value_count), 0) AS avg_latency
FROM metric_minute
WHERE ts_minute >= now() - INTERVAL 6 HOUR
AND tenant_id = 1001
AND metric_name = 'http.server.duration'
AND service_name = 'checkout'
GROUP BY ts_minute
ORDER BY ts_minute;
8. 冷热分层
可观测数据增长非常快, 推荐分层:
热数据: 最近 3-7 天, Doris 内表, 高副本, 索引完整
温数据: 最近 30-90 天, Doris 内表或对象存储, 保留核心索引
冷数据: 归档到 Iceberg/Hive/S3, 通过 External Catalog 查询
配套:
- 热表做自动分区。
- 到期分区删除或迁移。
- 高频报表做物化视图。
- 冷数据查询开启 Data Cache 或接受较高延迟。
9. 专家判断清单
1. 日志、指标、Trace 是否分表
2. 时间分区粒度是否匹配保留周期
3. 租户隔离字段是否进入查询条件和分布策略
4. 高频标签是否显式列化
5. 半结构化字段是否控制索引数量
6. 倒排索引是否真正有选择性
7. 热数据和冷数据是否分层
8. 查询是否有 LIMIT 和时间窗口
9. Profile 是否证明索引生效
10. 写入与 Compaction 是否仍可承受
一句话总结:
用 Doris 做可观测分析, 关键是把时间裁剪、租户隔离、文本检索、半结构化字段和冷热分层一起设计, 而不是只给日志表加一个倒排索引。