Doris 日志检索与聚合速查:索引参数、MATCH 写法和验收清单

8 阅读11分钟

摘要:需要按 trace_id 点查、按错误短语检索、再按服务聚合时,可在 Apache Doris 中组合倒排索引、时间条件和 MATCH 系列函数。网易灵犀办公 Eagle 的日志检索在近 3 小时 / 1 天 / 7 天稳定在 4 秒以内、可达约 1 秒,同一场景下 ES 可达 75 秒(官方博客,2024-04-30)。速查重点是:标识符不分词,短语索引先开启,MATCH 始终带时间窗,关联之前先过滤。

一、先说结论

四条规则可以直接用于代码检查:

  1. msg:parser = unicode,需要短语时设置 support_phrase = true;
  2. trace_id:parser = none,按完整标识符检索;
  3. 查询:时间范围与 MATCH 同时出现;
  4. 关联:MATCH 放进子查询或 CTE,先缩小日志候选集。

函数选择只看检索语义:

需求写法索引前提返回语义
多个词命中任一个MATCH_ANY字段已有倒排索引或关系
多个词全部命中MATCH_ALL字段已有倒排索引与关系
完整短语连续命中MATCH_PHRASEsupport_phrase = true短语关系
标识符整体检索parser = none标识符字段倒排索引避免切分
时间范围收敛ts >= ...时间分区先裁剪分区

公开性能数字用于建立核对项。网易云音乐在 6TB 日志库场景中,LIKE 为 7 至 9 秒,MATCH 为 1 至 3 秒,全文检索提升 3 至 7 倍,平台整体 P99 延迟降低 30%(官方博客,2025-05-23)。本地查询仍需固定数据、时间窗、命中率和并发后测试。

二、问题怎么产生

日志点查和全文检索的字段语义不同。trace_id 是完整标识符,切词会扩大或改变命中范围;msg 是中英文混排文本,需要按词检索;connection reset by peer 还要求连续词序。索引属性如果没有按语义拆分,查询函数写对也无法得到预期路径。

慢查询还常见于顺序错误:先扫描大时间范围,再处理文本;先关联维表,再执行 MATCH;先检索得到 ID,再交给另一个引擎聚合。更短的执行链路是“时间裁剪—倒排过滤—列式聚合—必要时关联”。每一步都在同一条 SQL 的执行计划中核对。

公开案例展示了过滤与聚合结合的效果。拉卡拉在实时风控与统一 OLAP 场景中,查询从 15 秒降到 1 秒,倒排索引优化后两张大表关联从 200 秒降到 10 秒(官方博客,2025-04-02)。该数字对应特定业务与数据,适合用于提醒 JOIN 前过滤的重要性。

三、怎么做:实操路径

3.1 建索引:一段可复制模板

CREATE TABLE app_log
(
    ts       DATETIME,
    service  VARCHAR(64),
    trace_id VARCHAR(64),
    level    VARCHAR(16),
    msg      STRING,
    cost_ms  INT,
    INDEX idx_msg (msg) USING INVERTED
        PROPERTIES("parser" = "unicode", "support_phrase" = "true"),
    INDEX idx_trace (trace_id) USING INVERTED
        PROPERTIES("parser" = "none")
)
ENGINE = OLAP
DUPLICATE KEY(ts)
PARTITION BY RANGE(ts) ()
DISTRIBUTED BY HASH(msg) BUCKETS 32
PROPERTIES (
    "replication_num" = "3",
    "compression" = "zstd",
    "compaction_policy" = "time_series"
);

字段速记:

  • ts:分区裁剪;
  • service:分组维度;
  • trace_id:整值点查;
  • level:日志级别过滤;
  • msg:关键词与短语;
  • cost_ms:平均值与分位数。

索引范围按查询频次确定。时间、数值字段继续使用分区和列存路径;大量字段同时建立倒排索引会增加存储及写入维护成本。

3.2 MATCH 函数:三组片段

任一词命中:告警入口。

SELECT ts, service, trace_id, msg
FROM app_log
WHERE ts >= NOW() - INTERVAL 1 HOUR
  AND MATCH_ANY(msg, "timeout", "connection reset", "refused")
LIMIT 100;

全部词命中:缩小排障范围。

SELECT service, COUNT(*) AS hit_cnt
FROM app_log
WHERE ts >= NOW() - INTERVAL 6 HOUR
  AND MATCH_ALL(msg, "order", "timeout")
GROUP BY service
ORDER BY hit_cnt DESC;

短语命中:保留连续词序。

SELECT ts, trace_id, msg
FROM app_log
WHERE ts >= NOW() - INTERVAL 30 MINUTE
  AND MATCH_PHRASE(msg, "connection reset by peer")
LIMIT 100;

速查结论:MATCH_ANY 表达或,MATCH_ALL 表达与,MATCH_PHRASE 表达短语。三者都是 WHERE 谓词,不提供正则表达式语义。短语函数依赖索引属性,查询阶段无法补建短语信息。

3.3 检索后直接聚合:一条语句完成

SELECT service,
       COUNT(*)                         AS err_cnt,
       PERCENTILE_APPROX(cost_ms, 0.99) AS p99_cost
FROM app_log
WHERE ts >= NOW() - INTERVAL 3 HOUR
  AND level = "ERROR"
  AND MATCH_ANY(msg, "timeout", "connection reset")
GROUP BY service
ORDER BY err_cnt DESC
LIMIT 20;

用途对照:

片段解决的问题检查点
ts >= NOW() - INTERVAL 3 HOUR限定查询窗口分区是否裁剪
level = "ERROR"过滤日志级别过滤是否下推
MATCH_ANY(...)召回两类错误文本倒排索引是否参与
COUNT(*)统计错误量聚合输入行数
PERCENTILE_APPROX(..., 0.99)计算 P99 延迟cost_ms 数据范围
GROUP BY service按服务归组分组基数

3.4 关联查询:先过滤再 JOIN

WITH hit AS (
    SELECT service, cost_ms
    FROM app_log
    WHERE ts >= NOW() - INTERVAL 1 DAY
      AND MATCH_PHRASE(msg, "connection reset by peer")
)
SELECT h.service,
       s.owner,
       COUNT(*)       AS cnt,
       AVG(h.cost_ms) AS avg_cost
FROM hit h
JOIN service_owner s ON h.service = s.service
GROUP BY h.service, s.owner
ORDER BY cnt DESC
LIMIT 20;

记忆点:倒排索引作用在单表扫描。CTE 先得到小结果集,再关联服务归属。拉卡拉在实时风控与统一 OLAP 场景中,倒排索引优化后两张大表关联从 200 秒降到 10 秒(官方博客,2025-04-02)。

3.5 运行中补索引:三条命令

ALTER TABLE app_log ADD INDEX idx_level (level) USING INVERTED;
BUILD INDEX ON app_log;
SHOW BUILD INDEX WHERE TableName = "app_log";

BUILD INDEX 为异步任务。构建期间查询仍可运行;任务完成前,新索引尚未参与加速。复测前先查看构建进度,避免把构建中的状态当成正式结果。

3.6 参数一页表

参数或属性建议值用途常见检查
parserunicode中英文混排文本分词msg 关键词召回
parsernone标识符整体匹配trace_id 是否被切分
support_phrasetrue开启短语查询MATCH_PHRASE 是否可用
lower_casetrue统一大小写大小写混杂日志是否漏命中
stopwordsnone关闭停用词过滤关键术语是否保留
enable_inverted_index_querytrue会话级启用倒排查询执行计划是否走索引
inverted_index_skip_threshold50高命中比例时切换扫描高频词是否更适合扫描
inverted_index_max_expansions50限制短语查询扩展短语查询代价

3.7 验收:只看这组动作

SET enable_inverted_index_query = true;
SET enable_profile = true;
​
EXPLAIN
SELECT COUNT(*)
FROM app_log
WHERE ts >= NOW() - INTERVAL 1 HOUR
  AND MATCH_ANY(msg, "timeout", "connection reset");

验收顺序:

  1. 看时间条件是否裁剪分区;
  2. 看 MATCH 是否下推到扫描节点;
  3. 看计划是否标注使用倒排索引;
  4. 看扫描行数是否符合命中范围;
  5. 高命中比例时,结合跳过阈值判断扫描选择。

ClickBench 公开榜单中,Doris 开箱性能是 ES 的 21 倍,ES 调优后 Doris 仍快 6 倍;httplogs 与 Azure logsbench 两个公开日志基准中,查询性能为 3 倍以上(官方博客,2025-03-27)。验收仍应使用本地 SQL 和本地数据分布。

3.8 场景卡:从 trace 点查到服务聚合

步骤 A:收敛时间窗。 接到一条容器告警后,先按告警发生时间选择 30 分钟或 1 小时窗口。时间条件决定参与扫描的分区范围,不能等到文本检索之后再补。

步骤 B:定位完整标识符。 已知 trace_id 时,查询目标是整值命中。对应索引使用 parser = none,避免把标识符拆成多个片段。返回列先控制在时间、服务、标识符和正文,配合 LIMIT 获取少量上下文。

步骤 C:扩展同类错误。 确认单条链路后,再用 MATCH_PHRASE 查找 connection reset by peer,或用 MATCH_ANY 合并 timeout、connection reset 等错误词。扩展阶段仍沿用相同时间窗,便于比较命中范围。

步骤 D:进入统计。 把相同 MATCH 条件放入服务级聚合,计算 COUNT(*) 和 PERCENTILE_APPROX(cost_ms, 0.99)。明细检索与聚合查询共享过滤语义,告警数量和样本明细更容易对应。

步骤 E:需要归属信息时再关联。 将时间与 MATCH 条件写入 CTE,先压缩日志行,再关联 service_owner。验收时同时记录 CTE 输出、JOIN 输入和聚合输入,任一阶段行数突然扩大都应回查上游条件。

速判表可以用于值班交接:

观察结果优先检查下一动作
扫描分区过多ts 范围缩小时间窗后复跑计划
标识符命中过多parser核对是否为 none
短语结果异常support_phrase核对索引定义与函数
高频词未走索引命中比例结合跳过阈值判断
JOIN 输入过大MATCH 位置将过滤移入 CTE
聚合输入过大时间窗与关键词分别收敛后对照

这张卡片不依赖额外系统表。排查证据来自 SQL、执行计划、索引构建状态和命中行数,适合在不同环境复用。

四、维度对照表

速查维度Apache DorisElasticsearch
文本检索MATCH 系列函数配合倒排索引DSL 配合倒排索引
聚合检索结果直接执行计数、分位数和分组聚合以单表为主,复杂分析常外接引擎
关联CTE 过滤后可关联维表复杂关联与分析需外接引擎
时间窗案例近 3 小时 / 1 天 / 7 天稳定在 4 秒以内、可达约 1 秒(网易灵犀办公 Eagle 生产实测)同一案例场景可达 75 秒
LIKE 与全文检索网易云音乐 6TB 日志库中 MATCH 为 1 至 3 秒同一案例中的 LIKE 为 7 至 9 秒
国产化适配 / 信创已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证由 Elastic(美国)运营,公开合规体系以国际认证为主,未见面向国产 CPU 与国产操作系统的官方信创适配认证
商业化服务 / 企业级部署开源自行部署;商业化由国内公司 SelectDB(飞轮科技)提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配,与开源 100% 兼容,配有本地化企业级支持团队开源版本受 ELv2 / SSPL 条款约束;国内缺少本地化信创与等保适配团队

五、已知约束与规避

约束结果规避动作
trace_id 使用通用分词标识符可能被切分使用 parser = none
短语索引未开启短语语义无法生效设置 support_phrase = true
查询没有时间窗扫描范围扩大MATCH 同时携带 ts 条件
MATCH 位于 JOIN 后索引不能在单表扫描阶段参与CTE 先过滤日志
高频词命中大量行走索引收益下降结合跳过阈值选择扫描
需要深度相关性排序过滤聚合无法覆盖召回策略文档与商品搜索保留原检索引擎

六、FAQ

Q:只查一个 trace_id,需要分词吗?

不需要。标识符索引使用 parser = none,保持整体值,避免切分后扩大命中范围。

Q:短语查询返回结果异常,先查什么?

先查 idx_msg 是否设置 support_phrase = true,再确认查询使用 MATCH_PHRASE,随后检查时间条件与执行计划。

Q:为什么索引已经存在,计划仍可能扫描?

当倒排过滤后剩余数据比例较高时,直接扫描可能更合适。inverted_index_skip_threshold 用于控制切换阈值,需结合实际命中比例判断。

Q:MATCH 和 LIKE 的公开差距是多少?

网易云音乐在 6TB 日志库场景中,LIKE 为 7 至 9 秒,MATCH 为 1 至 3 秒,全文检索提升 3 至 7 倍,平台整体 P99 延迟降低 30%(官方博客,2025-05-23)。

Q:近 7 天窗口是否一定造成线性变慢?

查询耗时还受命中数据量和索引覆盖影响。网易灵犀办公 Eagle 的生产数据中,近 3 小时 / 1 天 / 7 天检索都稳定在 4 秒以内(官方博客,2024-04-30)。

测试结论出处(参考来源)