《MySQL 索引机制彻底整明白:你查得慢,全是因为你索引不会用!》
摘要: MySQL索引是提升查询性能的关键,其本质是减少磁盘IO操作。索引类型包括主键、唯一、普通、联合、全文等,各有适用场景。聚簇索引(数据与索引一起存放)和非聚簇索引(需回表查询)是核心区别。使用索引需遵循最左前缀原则,避免计算、函数、模糊前缀和隐式转换。滥用索引会占用空间、降低写性能。通过EXPLAIN等工具分析执行计划,合理设计索引(如订单系统的user_id+create_time联合索
文章目录
🔥《MySQL 索引机制彻底整明白:你查得慢,全是因为你索引不会用!》
一、💽 MySQL 是“基于硬盘”的数据库,意味着啥?
意味着:它查数据靠“磁盘 IO”,这玩意巨他妈慢!
⚠ 数据在硬盘上,一查就要:
- 找文件
- 读数据页(通常是16KB)
- 缓慢旋转 + 移动磁头(机械硬盘更慢)
- 吞吞吐吐地塞给你结果
👉 如果你没有索引,那就是全表扫描!
100万条数据它一条条扫你试试!🐢慢如地狱
二、🧠 什么是索引?一言以蔽之:
就是数据库里的“目录”或者“查字典的拼音索引”,让你直接定位!
和你翻书类似:
- 没目录 → 从第一页翻起(全表扫描)
- 有目录 → 翻页精准定位(索引查找)
数据库索引的目标只有一个:
❗尽量少扫描数据页(减少磁盘 IO)!
三、📚 索引存在哪里?
在硬盘里!别听啥“索引在内存里”,那是缓存部分(buffer pool 预读了部分),完整的索引结构存在磁盘上的 .ibd 文件里。
MySQL 通过 InnoDB 引擎维护了一棵巨大的 B+Tree:
- 每个节点是一个 磁盘页(16KB)
- 每个页里放着一堆 key(主键 / 普通索引)
- 根节点 → 中间节点 → 叶子节点
- 每次查找最多 3~4 次磁盘 IO 就能命中
四、🧩 索引的几种类型(你必须搞清楚):
类型 | 用途 | 特点 |
---|---|---|
主键索引(Primary Key) | 按照主键建立的 B+Tree | 默认聚簇索引,数据和索引一起 |
唯一索引(Unique) | 不允许重复 | 邮箱、身份证 |
普通索引(Index) | 最常见,没啥限制 | 一般查询字段加这个 |
联合索引(Composite) | 多列组合 | 走最左前缀原则(重要⚠) |
全文索引(Fulltext) | 用于模糊/关键词搜索 | 比 like '%xxx%' 快一万倍 |
哈希索引(Memory引擎) | 内存中的Hash结构 | 查询快,但不能范围查询 |
空间索引(GIS) | 经纬度坐标点查找 | 不常用,GIS系统才有需求 |
五、🔍 聚簇索引 VS 非聚簇索引(重点来了)
聚簇索引(Clustered) | 非聚簇索引(Secondary) |
---|---|
数据和索引放在一起 | 索引存 key,值存主键地址 |
InnoDB 默认主键就是 | 普通字段建立的索引 |
查询快,更新慢 | 更新快,查值还得回表 |
👇 举个图解例子:
- 查主键 ID = 123 → 直接定位 → 数据拿到
- 查 name=‘张三’ → 查 name 的索引 → 找到 ID → 回表查数据
这就叫 回表查询(bookmark lookup)
六、📌 索引的使用规则(不会这些,索引白建)
-
✅ 最左前缀原则(联合索引杀手锏)
联合索引 ((a,b,c)
) 只会生效你条件是从左往右连续出现的- WHERE a = ? → √
- WHERE a = ? AND b = ? → √
- WHERE b = ? → ✘
-
❌ 不能在索引列上做计算或函数
- WHERE DATE(create_time) = ‘2023-01-01’ → 索引失效
改成: - WHERE create_time BETWEEN ‘2023-01-01’ AND ‘2023-01-01 23:59:59’ → √
- WHERE DATE(create_time) = ‘2023-01-01’ → 索引失效
-
❌ 不能用模糊前缀匹配
- LIKE ‘%张三%’ → 索引失效
- LIKE ‘张三%’ → √
-
✅ 范围查询后不能再用后面的字段索引
- WHERE a = 1 AND b > 3 AND c = 2 → 只用 a 和 b 的索引,c 失效
-
❗避免字段类型隐式转换
- WHERE phone = 13800138000 // phone 是 varchar → 索引失效
改成: - WHERE phone = ‘13800138000’ → √
- WHERE phone = 13800138000 // phone 是 varchar → 索引失效
七、🔥 为什么加了索引还是慢?
可能是:
- 索引没命中(比如顺序不对、类型转换)
- 索引选择性太差(比如性别字段,只是男女俩值)
- 回表太频繁(数据量大、字段太多)
- limit offset 过大(MySQL 会扫很多无用数据)
八、💣 滥用索引的代价:
有时候索引太多,不但查不快,还会拖慢系统!
坏处:
- 占空间(每个索引都是一棵树!)
- 增删改变慢(每次都要维护索引结构)
- 缓存命中率降低(太多数据页互相顶替)
九、工具推荐:
用这些命令 / 工具搞清楚你 SQL 是不是走索引👇
命令 | 作用 |
---|---|
EXPLAIN SELECT ... |
分析 SQL 执行计划(type, key, rows) |
SHOW INDEX FROM 表名 |
查看表上有哪些索引 |
SHOW CREATE TABLE 表名 |
一眼看出哪些字段有索引 |
[Navicat / DBeaver 可视化工具] | 帮你一眼看清表结构和索引 |
🔨 实战建议:
做一个“订单系统”:
order_id
是主键索引user_id
是普通索引create_time
建个联合索引(user_id, create_time)
- 查询订单列表:
WHERE user_id=? AND create_time BETWEEN ? AND ?
→ 极速!
🎯 总结句式(背下来!)
✅ 索引的目的是为了减少磁盘 IO
✅ 合理建索引是系统性能的灵魂
✅ 索引不是越多越好,得精心设计
✅ 不懂 B+Tree、最左前缀,那你就永远调不快 SQL
更多推荐
所有评论(0)