首页/数据/SQL 速查/B 树索引适用与不适用场景
性能与执行计划72 条

B 树索引适用与不适用场景

B 树索引支持等值、范围、前缀匹配与排序;对列上做运算、前置通配、类型不匹配的条件帮不上忙。

SQL 速查数据更新于 2026-10-13

B 树索引是什么

B+ 树索引是有序数据结构,支持等值、范围、前缀匹配(LIKE 'abc%')与排序,是 MySQL 与 PostgreSQL 的默认索引类型。它的边界也很清晰:在列上做函数运算、使用前置通配符(LIKE '%abc')、两侧类型不一致,都可能让索引无法定位范围。

基本信息

支持的操作=、>、>=、<、<=、BETWEEN、IN、ORDER BY、LIKE 前缀匹配
不支持前置通配、列上函数或表达式、类型隐式转换
复合索引遵循最左前缀原则,前导列缺失时后续列难以独立使用
排序索引顺序与 ORDER BY 一致时可省去额外排序步骤
代价占存储、增加写入与维护开销,多一个索引就多一次维护
两库差异基本行为一致,函数索引与部分索引的写法不同

能走索引的写法

能走索引的写法
-- 范围查询:B+ 树直接定位区间
SELECT * FROM orders
WHERE created_at >= '2024-01-01' AND created_at < '2024-02-01';

-- 前缀匹配
SELECT * FROM users WHERE name LIKE 'wang%';

-- 过滤加排序:复合索引 (user_id, created_at) 可同时满足
SELECT * FROM orders WHERE user_id = 100 ORDER BY created_at DESC LIMIT 10;

走不了索引的写法

走不了索引的写法
-- 列上包函数:索引的有序性被打乱
SELECT * FROM orders WHERE YEAR(created_at) = 2024;

-- 前置通配:索引按前缀有序,'%wang' 没有确定起点
SELECT * FROM users WHERE name LIKE '%wang';

-- 类型不匹配:字符串列与数字比较会触发隐式转换
SELECT * FROM users WHERE phone = 13800000000;   -- phone 列是 varchar

条件写法与索引可用性

条件写法能否用索引原因
col = 常量能等值定位
col > 常量 AND col < 常量能区间扫描
col LIKE 'abc%'能前缀有序
col LIKE '%abc'不能没有确定起点
FUNC(col) = 常量不能列被运算,有序性失效
col = 不同类型的常量视情况隐式转换可能让索引失效

典型使用场景

  • 高频等值与范围过滤的列上建索引
  • 复合索引同时覆盖过滤与排序,一次满足两种需求
  • 唯一索引保证业务键的唯一性
  • 外键关联列建索引,加快连接与级联操作
  • 用执行计划定期验证索引是否真的被用上
  • 清理长期未使用的冗余索引,降低写入开销
复合索引讲究最左前缀:索引 (a, b, c) 能用于 WHERE a = ? 与 a = ? AND b = ?,但对单独只用 b 的条件帮助有限。设计时把过滤频率高、选择性好的列放在前面。
索引不是越多越好:每个索引都会放大写入成本、占用缓冲池。上线新索引前先评估查询频率与读写比,并在业务低峰执行建索引操作。

易错点

  • 以为加了索引就一定生效:列上运算、前置通配、类型不一致都会让索引失效,必须用执行计划确认
  • 复合索引列顺序随意:前导列用不上时后续列也难独立发挥作用,按查询条件安排顺序
  • 小表也迷信索引:返回大量行的查询走全表扫描可能更快,索引还会带来维护成本
  • 给低选择性列单独建索引:只有几个取值的列索引意义有限,应该放在复合索引的后位
  • 忽略隐式类型转换:数字列与字符串常量比较时可能触发转换,索引与查询结果都会受影响

数据来源与参考

  • MySQL 8.0 Reference Manual §8.3.1 How MySQL Uses Indexes
  • PostgreSQL Documentation §11.2 Index Types
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌