MySQL 8.0.16使用转义符时未命中索引问题咨询
问题原因解析
1. 高数据占比触发优化器全表扫描选择
当model_type列中App\Models\Ad的值占总行数76%时,MySQL优化器会做成本计算:走索引需要先遍历索引找到对应条目,再回表读取完整数据;而全表扫描可以直接一次性获取所有符合条件的行,对于这种超大规模的匹配场景,全表扫描的开销反而更低。因此优化器主动放弃索引,执行计划显示type: ALL。
这是MySQL优化器的常规逻辑——当匹配行数超过总数据量的30%左右时,全表扫描通常比索引查询更高效。
2. 转义符引发的匹配逻辑差异
虽然'App\\\\Models\\\\Ad'解析后和'App\Models\Ad'是完全相同的字符串,但在执行计划生成阶段,MySQL对带转义符的查询字符串可能会进行额外的语法解析处理,导致优化器没有直接关联到索引中的目标值,进一步强化了选择全表扫描的决策。
如果你的media_model_type_model_id_index是model_type+model_id的联合索引,只查询model_type时,索引的利用效率本就不如单独的model_type索引,再加上高数据占比的影响,更容易触发全表扫描。
验证方式
- 强制使用索引,对比执行计划:
若此时EXPLAIN SELECT * FROM media FORCE INDEX(media_model_type_model_id_index) WHERE model_type = 'App\\\\Models\\\\Ad';type变为ref或range,则说明优化器确实是因数据占比放弃了索引。 - 查看列值分布,确认占比情况:
SELECT model_type, COUNT(*) AS cnt, ROUND(COUNT(*)/(SELECT COUNT(*) FROM media)*100,2) AS ratio FROM media GROUP BY model_type ORDER BY ratio DESC;
结论
核心原因是目标值的数据占比过高,优化器基于成本选择了全表扫描;转义符的使用只是触发了优化器的不同判断路径,并非根本原因。
内容的提问来源于stack exchange,提问作者Fredrik
相关产品推荐
相关产品推荐

