真实耗时分析需分层使用:EXPLAIN ANALYZE提供单次执行快照,performance_schema支持无侵入历史趋势监控,slow_query_log(long_query_time=0)捕获全量原始证据链,三者协同定位性能根因。

直接看真实耗时,用 EXPLAIN ANALYZE;想查历史耗时分布或长期监控,必须走 performance_schema;别再依赖已废弃的 SHOW PROFILES。
EXPLAIN ANALYZE 能看到什么、不能看到什么
它会真实执行语句(注意副作用!),返回每个执行节点的 actual_time(单位微秒)、rows_examined、loops 等实测值。但有几点必须清楚:
-
EXPLAIN ANALYZE不适合在生产环境对写操作、大结果集或高并发场景直接跑——它真读数据、真加锁、真触发 I/O - 输出里
actual time=0.045..12.402表示该节点从开始到结束耗时约 12.36ms,不是平均值;若loops=10,则这个时间是单次均值,总耗时需乘以 10 - 它不提供锁等待、网络延迟、CPU 调度等外部开销,只反映语句在 MySQL 内部的执行片段
- JSON 格式输出更全:
EXPLAIN FORMAT=JSON ANALYZE SELECT ...,能看清 nested loop 的嵌套关系和累加逻辑
为什么 performance_schema 比 EXPLAIN ANALYZE 更适合线上观察
因为 performance_schema 是无侵入式采样,不改变语句行为,且保留历史窗口。关键表和查询如下:
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 查最近最耗时的 10 条语句:
SELECT DIGEST_TEXT, AVG_TIMER_WAIT/1000000000 AS avg_sec, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY AVG_TIMER_WAIT DESC LIMIT 10 - 查某条语句的真实扫描行数与锁等待:
SELECT SQL_TEXT, TIMER_WAIT/1000000000 AS exec_sec, LOCK_TIME/1000000000 AS lock_sec, ROWS_EXAMINED, ROWS_SENT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE '%your_table%' - 确保开关已打开:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements%';,否则表为空
slow_query_log = 0 是最轻量的全量捕获方式
把慢日志阈值设为 0,等于记录所有查询,配合 pt-query-digest 或 mysqldumpslow 分析,比临时开 general_log 更可控:
- 配置项必须同时生效:
slow_query_log = ON、long_query_time = 0、log_output = FILE(或TABLE) - 开启后日志体积增长快,建议搭配
log_rotation或定时轮转脚本,避免磁盘打满 -
log_queries_not_using_indexes = ON可辅助发现隐式全表扫描,但要注意:小表或命中缓存时,优化器可能主动放弃索引,这不一定是问题
真实耗时永远藏在运行时上下文中——EXPLAIN ANALYZE 给你单次快照,performance_schema 给你趋势水位,slow_query_log 给你原始证据链。三者不是替代关系,而是分层定位:先用慢日志捞出异常语句,再用 performance_schema 查它最近几次的 LOCK_TIME 和 ROWS_EXAMINED 是否波动,最后对准具体某次调用,用 EXPLAIN ANALYZE 拆解内部循环开销。漏掉任意一层,都可能把锁等待当成 SQL 本身慢。










