You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么MySQL InnoDB中带LIKE '%%'的COUNT查询比无过滤COUNT更快?

InnoDB 下两类 COUNT 查询性能差异的核心原因

首先明确基础前提:InnoDB 不像 MyISAM 内置了全局表行数缓存,所有 COUNT 统计都需要实际扫描存储结构计算,不存在直接读预存行数的捷径。

第一组无过滤查询慢的原因

你跑的这两条无任何 WHERE 条件的语句:

SELECT COUNT(*) FROM tb_user
SELECT COUNT(idx_user_name) FROM tb_user

对应执行计划走的是全表扫描(type=ALL):优化器做成本估算时,没有选择idx_user_name二级索引,而是直接扫描聚簇索引(主键索引)统计行数。

  • 聚簇索引的叶子节点存的是整行所有字段的完整数据,100万行的聚簇索引占用的磁盘空间大,扫描过程需要加载大量数据页到内存,IO成本很高,所以耗时达到2.5秒。
  • 因为两个语句都走了同一条全表扫描的执行路径,所以耗时几乎完全一致。

第二组带LIKE '%%'查询快的原因

加了WHERE idx_user_name LIKE '%%'的两条语句,看起来条件完全没过滤效果(前后通配符会匹配所有非NULL的字段值,等于不筛掉任何行),但实际给优化器传递了明确的信号:本次查询只需要访问idx_user_name这个索引包含的字段就能完成计算。

  • 这时候优化器会选择覆盖索引扫描,直接遍历idx_user_name这个唯一二级索引的叶子节点统计行数。
  • 二级索引的叶子节点只存索引列值 + 对应的主键ID,不存其他无关的行字段,单个数据页能存的索引条目数是聚簇索引的好几倍,100万行的二级索引整体体积小很多,扫描需要加载的磁盘页极少,IO成本骤降,所以耗时只有0.3秒。

几个补充说明:

  • 无过滤条件时优化器不主动选二级索引,是MySQL 5.7及更早版本的常见成本计算偏差:优化器错误给二级索引路径加上了回表的成本预估,但COUNT统计根本不需要回表取整行数据,才会选错执行路径;部分8.0版本已经修正了这个逻辑,但统计信息不准时还是可能出现同类问题。
  • 想要无过滤COUNT也达到0.3秒的性能,可以手动强制走索引:SELECT COUNT(*) FROM tb_user FORCE INDEX(idx_user_name),执行效率和加LIKE '%%'完全一样。
  • 这里COUNT(*)和COUNT(idx_user_name)性能没有差异,是因为InnoDB对COUNT(*)做了专门优化,不需要判断字段是否为空,碰到行就直接计数;走二级索引时COUNT(索引列)只需要判断索引列非空就计数,两者计算成本几乎没有差别。

内容的提问来源于stack exchange,提问作者zby001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:21:51