日志平台最缺的不是存储,是查询。本文介绍炬鲸的 SQL 化检索:用 SELECT、WHERE、GROUP BY 直接在海量日志上过滤、聚合与关联,附可直接套用的语句模板与性能建议。
日志平台最常见的痛点不是存不下,而是查不动。关键词搜索只能定位"某句话",一旦要回答"过去 24 小时错误率最高的 5 个接口""哪些 pod 的 GC 停顿最严重"这类问题,就只能逐页翻,或者导出后自己写脚本处理。炬鲸把日志组织成一张可查询的表,支持标准 SQL:SELECT 做投影、WHERE 过滤、GROUP BY 聚合、JOIN 关联,一条语句顶过去半小时的手工翻页。对运维和开发来说 SQL 是现成技能,学习成本几乎为零,排查口径也更容易在团队里统一。
采集时解析出的字段(服务名、级别、耗时、trace_id、pod 等)在 SQL 里就是列名。查某个服务近一小时内的 ERROR 日志:
SELECT timestamp, message, pod
FROM logs
WHERE service = 'order-service'
AND level = 'ERROR'
AND timestamp > now() - INTERVAL 1 HOUR
ORDER BY timestamp DESC
LIMIT 100;
列名可以起中文别名,方便把语句直接贴给不熟 SQL 的同事:
SELECT level AS 级别, count(*) AS 条数
FROM logs
WHERE timestamp > now() - INTERVAL 1 HOUR
GROUP BY level;
嵌套字段(如 JSON 里的 request.user_id)用点号访问即可,和查普通列一样,不需要先解析再查。
聚合才是 SQL 查日志真正值钱的地方。排查"哪个接口拖慢了整体",一条语句搞定:
SELECT api_path,
avg(duration_ms) AS avg_ms,
p99(duration_ms) AS p99_ms,
count(*) AS cnt
FROM logs
WHERE level = 'INFO'
AND duration_ms IS NOT NULL
AND timestamp > now() - INTERVAL 1 HOUR
GROUP BY api_path
ORDER BY p99_ms DESC
LIMIT 20;
p99、p95 这类分位聚合函数内置,不用自己实现。关联同样顺手:用 trace_id 把一次慢请求的所有日志串成一条调用链,从网关到数据库逐跳看耗时,直接定位卡在哪一跳。还可以把错误日志按 trace_id JOIN 到告警表,做到"告警即带调用链",值班人员点开告警就能看到上下文。
要让 SQL 查日志快,养成两个习惯:一是永远带时间范围,全表扫描是慢查询的最大来源;二是把高频过滤字段建索引。炬鲸写入侧按时间自动分区,查询侧对 service、level、trace_id 预建索引,几十亿条日志里上面的语句依然秒级返回。复杂聚合建议走异步任务,结果落成报表定时推送,别在排查高峰期和实时检索抢资源。对重复使用的语句,存成"保存查询"并共享给团队,比每次手敲更快也更不容易出错。