MySQL查询中Like前缀模糊查询为什么不走索引_解析B+树搜索原理

阿瑶酱_3085

阿瑶酱_3085

2026-05-19

341人浏览

原创

like 'abc%'可走索引,因b+树支持前缀匹配,能定位起始点并range扫描;而'%abc'和'%abc%'无法定位起点,必须全表扫描,与配置或优化器无关。

mysql查询中like前缀模糊查询为什么不走索引_解析b+树搜索原理

MySQL 的 LIKE 'abc%' 能走索引,但 LIKE '%abc'LIKE '%abc%' 一定不走——这不是配置问题,也不是优化器“没选对”,而是 B+ 树索引结构本身就不支持后缀或中缀查找。

为什么 LIKE 'abc%' 可以用上索引

B+ 树索引按字典序严格排序,所有键值从左到右逐字符可比。LIKE 'abc%' 提供了确定的前缀,优化器能快速二分定位到第一个 ≥ 'abc' 的索引项(比如 'abc''abcd''abce_123'),然后向右顺序遍历直到遇到 'abd' 开头的记录为止。

这个过程本质是 range 扫描,EXPLAIN 中会显示:type=rangekey=xxxrows 明显小于总行数。

  • 只要前缀固定(哪怕带中文、emoji、特殊符号),都适用,例如 name LIKE '张%'path LIKE '/api/v2%'
  • 组合索引中,仅最左字段满足前缀匹配才生效;INDEX(name, age) 下,WHERE name LIKE '李%' 有效,WHERE age LIKE '2%' 完全无效
  • 若字段定义为 utf8mb4_0900_as_cs,而查询参数用了不同 collation(如 utf8mb4_general_ci),可能触发隐式转换,导致索引失效

为什么 LIKE '%abc' 绝对不走索引

后缀匹配要求“结尾是 abc”,但 B+ 树里 'xabc''helloabc''abc' 这些值在物理存储上完全离散,可能分布在树的不同层级甚至不同叶子页。没有起始点,就无法利用树的有序性跳转——只能全量读取所有叶子节点做字符串截取 + 比较,这比直接全表扫描还多一层索引页 IO 开销。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载

EXPLAIN 必然显示:type=ALLkey=NULLrows ≈ 表总行数。加 FORCE INDEX 也无效,不是优化器“不肯”,是引擎层压根不支持这种扫描模式。

  • 常见误判:看到 type=range 就以为走了索引?错。某些旧版本 MySQL 在统计信息异常时可能误标,但只要 rows 接近全表,实际就是伪 range,性能无改善
  • UPPER(name) LIKE '%ABC' 同样失效,函数包裹会让索引键不可直接比较;可用函数索引补救:CREATE INDEX idx_name_upper ON t1 ((UPPER(name)))
  • 参数化拼接如 WHERE name LIKE CONCAT('%', ?),预编译阶段无法推导字面量前缀,优化器静态分析失败,索引被跳过

为什么 LIKE '%abc%' 也不走索引

中缀匹配更复杂:既无确定起点,也无确定终点。“包含 abc” 的字符串在索引中彻底无序分布,B+ 树无法构造任何有效扫描边界。即使某行数据恰好命中索引页缓存,引擎仍需逐行取出完整值,再用 CPU 做 strstr() 类判断。

它和 LIKE '%abc' 属于同一类失效场景,只是语义上更宽泛。别信“加覆盖索引就能加速”的说法——覆盖索引只省回表,不省匹配逻辑,rows 仍是全扫。

  • 字段类型与参数类型不一致会雪上加霜,例如 name VARCHAR(50) 被写成 WHERE name LIKE 123,触发隐式转换,索引彻底作废
  • 即便把 collation 强制统一(如加 COLLATE utf8mb4_bin),也改不了索引结构限制,只是避免额外转换开销
  • 全文索引(FULLTEXT)或生成列反转(REVERSE(name) + 普通索引)是唯二可行替代路径,但各有适用边界:前者不支持短词、后者只解后缀

真正容易被忽略的是:索引是否生效,不能只看 EXPLAINtypekey,必须核对 rows 是否显著下降。很多线上慢查表面“走了索引”,实则是 rows 几乎等于表行数,本质仍是暴力扫描——这时与其调优 SQL,不如重构查询语义或引入外部检索能力。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

mysql

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3703

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

791

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

949

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5481

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2483

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5480

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7101

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

970

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

852

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 169人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 273人学习