不能直接用 show profile 比较 innodb 和 myisam,因为其阶段名是 sql 层统一抽象,不反映引擎底层行为差异,且 mysql 8.0 已移除该功能。

SET profiling = 1 对当前会话生效,但无法跨引擎对比——因为 profiling 不记录存储引擎底层行为差异,只反映 SQL 层执行阶段耗时。真正能体现引擎差异的,是 Sending data、Copying to tmp table、Sorting result 这些阶段的持续时间与资源分布,而非引擎名本身。
为什么不能直接用 SHOW PROFILE 比较 InnoDB 和 MyISAM?
SHOW PROFILE FOR QUERY N 输出的阶段名(如 executing、Sending data)是 SQL 层统一抽象,不区分引擎内部实现。比如同样一个 ORDER BY,InnoDB 可能走聚簇索引扫描+内存排序,MyISAM 可能全表扫描+磁盘临时表——但 profiling 都只标为 Sorting result 或 Creating tmp table,不会写 “InnoDB buffer pool read” 或 “MyISAM key cache hit”。
更关键的是:profiling 在 MySQL 8.0 已被移除,5.7 起就标记为 deprecated;你看到的耗时数据可能因版本、并发、缓存状态而抖动,同一查询两次执行,SHOW PROFILES 甚至可能漏掉阶段。
- 同一语句在不同引擎下,
Opening tables耗时可能差异巨大(MyISAM 表打开快,但锁粒度粗;InnoDB 打开略慢,但支持行锁) -
System lock阶段在 MyISAM 中常出现(表级锁),InnoDB 中极少——但 profiling 不告诉你这是哪种锁,只写 “System lock” -
Duration总和不含锁等待时间,如果 MyISAM 查询卡在Waiting for table level lock,profiling 完全不统计这段
怎么实操对比两种引擎的真实差异?
必须绕过 profiling,改用三组互补指标:
- 先用
EXPLAIN FORMAT=JSON看执行计划:确认是否都走了索引、rows_examined是否接近、used_filesort或used_temporary是否开启 - 再开慢日志并设
long_query_time = 0.01,执行相同 SQL 两次(分别ALTER TABLE t ENGINE=InnoDB/ENGINE=MyISAM),抓取Query_time、Lock_time、Rows_examined、InnoDB_pages_distinct(8.0.26+)等字段 - 最后查
performance_schema.events_statements_history_long:用TIMER_WAIT(单位皮秒)算真实耗时,并关联events_stages_history_long看stage/sql/Sending data等阶段是否触发了磁盘 IO(stage/innodb/row_lock_waits或stage/myisam/ha_rkey)
注意:MyISAM 表必须显式 FLUSH TABLES 再测,否则 key_buffer 可能命中缓存;InnoDB 则需预热 buffer pool,否则首次读全是磁盘 IO。
最容易被忽略的陷阱:临时表位置决定性能分水岭
当查询含 GROUP BY 或 ORDER BY 且无合适索引时,InnoDB 和 MyISAM 都可能建临时表,但策略不同:
- InnoDB 默认用
tmp_table_size和max_heap_table_size控制内存临时表上限,超限则落盘到innodb_temp_data_home_dir - MyISAM 临时表始终写磁盘(
/tmp或tmpdir),不走内存 - 所以即使
SHOW PROFILE显示两者Creating tmp table耗时接近,实际 I/O 压力天差地别——InnoDB 可能只是内存分配慢,MyISAM 是真写磁盘
验证方法:执行前 SELECT @@tmp_table_size, @@max_heap_table_size;,再查 SHOW GLOBAL STATUS LIKE 'Created_tmp%';,对比两次查询后 Created_tmp_disk_tables 是否增长。
profiling 的阶段耗时只能帮你发现“哪一步慢”,但没法告诉你“为什么慢”——尤其在跨引擎对比时,它连锁类型、缓冲区命中、页分裂这些关键信号都不暴露。真要定位引擎差异,得靠 EXPLAIN + 慢日志 + performance_schema 三层印证,而不是盯着 SHOW PROFILE CPU FOR QUERY 1 的那几毫秒。











