query_log 记录什么
system.query_log 记录每条查询的类型、耗时、读取行数与字节数、内存峰值与异常信息。它是定位慢查询、分析扫描量、验证排序键是否生效的主要数据源:只看总耗时容易误判,配合 read_rows 与 read_bytes 才能判断瓶颈在扫描还是计算。
基本信息
| 关键列 | type、query_duration_ms、read_rows、read_bytes、memory_usage、query |
|---|---|
| type 取值 | QueryStart、QueryFinish、ExceptionWhileProcessing |
| 常用过滤 | type = 'QueryFinish' 只看完成的查询,is_initial_query = 1 只看客户端发起的初始查询 |
| 写入方式 | 按秒级间隔异步刷盘,刚结束的查询可能暂时不可见 |
| 启用状态 | 部分版本与配置下需要显式开启,分析前先确认表里有数据 |
典型使用场景
- 定位慢查询:按耗时排序,先处理代价最高的请求
- 检查排序键设计:read_rows 远大于返回行数说明扫描面过大
- 评估内存压力:找出 memory_usage 峰值接近实例上限的查询
- 排查报错:type 为 ExceptionWhileProcessing 的记录带失败原因
- 容量规划:统计单位时间的查询量用于扩容评估
常用查询
常用查询
-- 最近一小时最慢的十条查询
SELECT query_duration_ms, read_rows, formatReadableSize(read_bytes) AS read_size,
substring(query, 1, 80) AS q
FROM system.query_log
WHERE type = 'QueryFinish' AND event_time >= now() - INTERVAL 1 HOUR
ORDER BY query_duration_ms DESC LIMIT 10;
-- 扫描量最大的查询:优化排序键的目标
SELECT query_duration_ms, read_rows, read_bytes, substring(query, 1, 120) AS q
FROM system.query_log
WHERE type = 'QueryFinish' AND event_time >= now() - INTERVAL 1 HOUR
ORDER BY read_rows DESC LIMIT 10;
-- 失败查询与原因
SELECT event_time, exception_code, exception, substring(query, 1, 80) AS q
FROM system.query_log
WHERE type = 'ExceptionWhileProcessing' AND event_time >= now() - INTERVAL 1 DAY
ORDER BY event_time DESC LIMIT 20;关键列读法
| 列 | 含义 | 怎么看 |
|---|---|---|
| type | 记录类型 | 只看性能要过滤 QueryFinish |
| query_duration_ms | 查询耗时 | 总耗时高不一定扫描多,要并看读取量 |
| read_rows | 读取的行数 | 远大于返回行数说明排序键没起作用 |
| read_bytes | 读取的字节数 | 与 read_rows 一起判断是列裁剪还是行裁剪问题 |
| memory_usage | 内存峰值 | 接近实例上限的查询存在 OOM 风险 |
| exception_code | 异常码 | 非 0 时结合 exception 字段看原因 |
query_log 自身也占磁盘,长期保留要设置 TTL 或降低采样比例;分析前先确认它已启用且字段有数据,否则会把「没有数据」误判成「没有问题」。
验证优化效果时对比同一查询优化前后的 read_rows 与 read_bytes 比只看耗时更可靠:耗时受并发与缓存影响,扫描量直接反映排序键与分区裁剪是否生效。