MySQL数据库基本概念中什么是索引?索引类型与查询优化机制解析

来源:这里教程网 时间:2026-02-28 20:53:03 作者:

索引就是数据库的“目录”,不是附加功能,而是查询加速的底层数据结构

索引在MySQL里不是锦上添花的配置项,而是直接决定

SELECT
快慢的核心机制。它本质是一棵B+Tree(InnoDB默认),存储的是「字段值 + 对应行的物理位置」,而不是复制整行数据。没有索引时,MySQL只能全表扫描——比如查100万行里的某条记录,平均要读50万行;加了索引后,通常3~4次磁盘IO就能定位,性能差上百倍。关键点在于:索引生效的前提是查询条件能命中索引结构,否则它就只是白占空间、拖慢
INSERT/UPDATE/DELETE

B-Tree索引为什么是主力?Hash和全文索引哪些场景不能用

InnoDB只支持B-Tree索引(实际是B+Tree变种),因为它能同时支撑等值查询、范围查询(

>
BETWEEN
)、排序(
ORDER BY
)和最左前缀匹配。而
Hash索引
仅Memory引擎原生支持,且只响应完整等值查询(
WHERE col = ?
),不支持
col > 100
WHERE col1 = ? AND col2 > ?
FULLTEXT
索引专用于
MATCH() AGAINST()
全文检索,但对中文需额外分词插件(MySQL原生不支持),且无法用于
WHERE col LIKE '%xx%'
这类模糊查询。

别在
datetime
字段上建Hash索引——语法会通过,但InnoDB会静默转成B-Tree
FULLTEXT
必须建在
CHAR/VARCHAR/TEXT
列上,且建表时指定
ENGINE=InnoDB
(5.6.4+)
联合索引
(a,b,c)
WHERE a=1 AND b>10
有效,但对
WHERE b>10
完全无效

什么时候加索引?看执行计划比猜更可靠

别凭感觉加索引。先用

EXPLAIN
看查询是否走了索引:
EXPLAIN SELECT * FROM orders WHERE user_id = 123;
。重点看
type
字段——
const
/
ref
表示高效命中,
range
尚可,
ALL
就是全表扫描。再检查
key
列是否显示用了哪个索引,
rows
是否远小于表总行数。常见误判点:

单列索引
user_id
和联合索引
(user_id, status)
共存时,优化器可能选错,用
FORCE INDEX
临时干预
OR
条件容易让索引失效,比如
WHERE a=1 OR b=2
,建议拆成
UNION
或补上复合索引
LIKE
以通配符开头(
LIKE '%abc'
)必然无法用B-Tree索引,这是结构限制,不是配置问题

索引不是越多越好:维护成本和写放大必须算进账

每多一个索引,

INSERT
就要多写一棵B+Tree叶子节点,
UPDATE
改索引列时还要分裂页、合并页。线上表如果QPS高、写入频繁,盲目加索引反而导致
innodb_row_lock_waits
飙升。真实案例:某订单表加了5个冗余索引后,日均慢查没降,但磁盘IO等待从2ms涨到18ms。建议做法:

information_schema.STATISTICS
定期查未被使用的索引:
SELECT * FROM STATISTICS WHERE TABLE_SCHEMA='db' AND INDEX_NAME NOT IN (SELECT DISTINCT INDEX_NAME FROM performance_schema.events_statements_summary_by_digest WHERE DIGEST_TEXT LIKE '%table%');
删除索引前先在测试环境开
slow_query_log
并设
long_query_time=0
,跑一周业务流量,确认无慢查回归
联合索引优先覆盖高频查询组合,宁可少建两个单列索引,也不要建三个互相重叠的联合索引

最常被忽略的一点:索引字段顺序直接影响过滤效率。比如用户登录常用

WHERE email = ? AND status = 'active'
,那
(email, status)
(status, email)
高效得多——因为status的区分度通常远低于email,放前面会导致B+Tree第一层就过滤不掉多少数据。

相关推荐