索引通过B+树结构实现快速查找,跳过全表扫描;支持有序读取以避免排序/分组计算;需遵循最左前缀原则;隐式转换、函数操作、非前缀LIKE等会导致失效;索引并非越多越好,应权衡读写性能与业务需求。

索引跳过了全表扫描这一步
SQL 查询慢,最常见原因就是数据库要逐行检查每条记录是否满足 WHERE 条件。索引本质是一棵有序的数据结构(通常是 B+ 树),它把某列(或几列)的值提前排好序,并存了对应行的物理位置。查询时,数据库直接在索引里二分查找目标值,定位到少数几个叶子节点,再回表取数据——省掉了从头扫到尾的过程。
比如执行 SELECT * FROM users WHERE user_id = 123;,如果 user_id 有主键索引,数据库就不用读取整个 users 表,而是查索引树,几步就找到那一条记录的位置。
注意:只有当查询条件能“走索引”时才跳过全表扫描,比如 WHERE status = 'active' 对没有索引的 status 列,依然会全表扫。
索引让排序和分组不再现场计算
当查询包含 ORDER BY 或 GROUP BY,且字段上有合适索引时,数据库可以直接按索引顺序读取数据,无需额外排序或哈希分组。
例如:SELECT name FROM users ORDER BY created_at DESC LIMIT 10;,若 created_at 上有索引,数据库就能从索引末尾往前取 10 条,连内存排序都省了。
但要注意索引顺序必须匹配:如果建的是 INDEX (a, b),那么 ORDER BY a, b 可用,ORDER BY b 就用不上;ORDER BY a DESC, b ASC 在 MySQL 8.0+ 才支持混合方向,旧版本可能失效。
常见坑:
-
隐式类型转换会让索引失效,比如
WHERE phone = 13800138000(phone是字符串类型) -
LIKE '%abc'无法使用索引前缀匹配,LIKE 'abc%'才可以 - 对索引列做函数操作,如
WHERE YEAR(created_at) = 2023,索引失效
联合索引的最左前缀原则不是玄学
联合索引 INDEX (a, b, c) 实际上构建了一棵按 a → b → c 排序的树。这意味着它可以高效服务以下查询:
系统功能强大、操作便捷并具有高度延续开发的内容与知识管理系统,并可集合系统强大的新闻、产品、下载、人才、留言、搜索引擎优化、等功能模块,为企业部门提供一个简单、易用、开放、可扩展的企业信息门户平台或电子商务运行平台。开发人员为脆弱页面专门设计了防刷新系统,自动阻止恶意访问和攻击;安全检查应用于每一处代码中,每个提交到系统查询语句中的变量都经过过滤,可自动屏蔽恶意攻击代码,从而全面防止SQL注入攻击
WHERE a = 1WHERE a = 1 AND b = 2WHERE a = 1 AND b = 2 AND c = 3-
WHERE a = 1 AND b IN (2,4) AND c = 3(部分优化器支持)
但它不能加速:
-
WHERE b = 2(没用到a,跳不过第一层) -
WHERE a > 1 AND c = 3(c不在索引连续路径上)
所以建联合索引时,高频等值查询字段放左边,范围查询(>, BETWEEN)字段放中间,排序/分组字段放右边——顺序错了,索引就白建。
索引不是越多越好,写多读少时反而拖慢性能
每次 INSERT、UPDATE、DELETE 都要同步更新所有相关索引。一个表有 5 个索引,写一行可能要写 6 次磁盘(1 次数据页 + 5 次索引页)。
更隐蔽的问题是:
- 索引占用内存和磁盘空间,降低缓冲池命中率
- 优化器可能选错索引,尤其当统计信息过期或数据倾斜严重时
- 唯一索引冲突检查、外键约束验证都会因索引变多而变重
真正需要索引的,是那些出现在 WHERE、JOIN ON、ORDER BY、GROUP BY 中,且选择性高(去重后值多)、查询频次高的字段。其他一律先观察,别一上来就加。
复杂点在于:同一张表上不同业务 SQL 的访问模式可能互相冲突,比如 A 业务要 (a,b),B 业务要 (b,c),这时候得权衡覆盖度、维护成本和写入压力——没有银弹,只有取舍。









