← 返回文章列表
产品动态 4 分钟阅读 炬鲸团队

用 SQL 查日志:把日志当数据库来检索

炬鲸 OBSERVE 的类 SQL 检索把日志解析成结构化字段,用 SQL 完成过滤、聚合、排序。本文给出可直接粘贴的查询、字段与索引设计建议,以及排障时的典型用法。

为什么用 SQL 查日志

运维和开发本来就熟悉 SQL。用 grep 翻日志没问题,但遇到「统计过去一小时各服务的 5xx 数量」「找出响应时间超过 2 秒的接口」这类需求,grep 加 awk 要写一大段还容易错。炬鲸 OBSERVE 把日志解析成结构化字段,直接当表来查:过滤、聚合、排序、子查询都能用,几乎零学习成本。

排障时差别更明显:用 grep 是搜关键词再人肉看结果,用 SQL 是直接提问——「过去 15 分钟哪个服务错误率跳得最狠」——一条语句就给出排序答案,还能存下来给全组复用。

几条可以直接用的查询

-- 过去 1 小时各服务的 5xx 数量
SELECT service, count(*) AS cnt
FROM logs
WHERE status >= 500 AND __time__ > now() - interval '1' hour
GROUP BY service
ORDER BY cnt DESC;

-- 响应时间超 2 秒的接口,按路径聚合
SELECT path, max(latency) AS slowest
FROM logs
WHERE latency IS NOT NULL
GROUP BY path
HAVING max(latency) > 2000;

-- 近 24 小时错误率最高的服务 Top 5
SELECT service,
       count_if(status >= 500) AS errors,
       count(*) AS total,
       count_if(status >= 500) * 1.0 / count(*) AS err_rate
FROM logs
WHERE __time__ > now() - interval '24' hour
GROUP BY service
HAVING count(*) > 1000
ORDER BY err_rate DESC
LIMIT 5;

字段名和采集端解析规则一致。接入时在 Pipeline 里把 statuslatencypath 定义成结构化字段,查询就能直接引用,不用另维护一份 schema。

字段与索引怎么设计

结构化是前提。以 nginx 日志为例,用 grok 拆出 remote_addrstatuslatencypath 后写入。类型要显式声明:latency 用数值类型、status 用整型,否则全部按字符串处理,排序和比较会乱。这是最常见的一个坑,表现就是「查询能跑但顺序是错的」。

查询侧几个建议:

  • 高频字段加索引,减少扫描量;
  • 先过滤后聚合,WHERE 条件写全,别聚合完再过滤;
  • 大表查询一定带时间范围,避免全表扫描拖垮集群。

排障时怎么用

排障最常用的三步:先按时间范围加关键词圈定范围,再用 trace_idrequest_id 关联上下游,最后按聚合结果定位异常来源。每一步都能存成查询模板,值班时直接调用,不用半夜现写。多服务联调时,把 trace 和日志放在同一个查询里做 JOIN,一条 SQL 就能还原整条调用链。

和专用查询语言的差别

不少日志平台有自己的一套 DSL,语法记不住、换个平台就作废。SQL 是通用技能,团队里人人会写,新人上手不用培训。它既能做简单的关键词过滤,也能写带子查询、窗口函数的复杂分析,同一个引擎覆盖从排障到报表的全部需求。