【MySQL-索引调优】06:最左匹配原则及优化

最左匹配原则

PS:现在orders表中存在idx_user_id(user_id),以及idx_user_status(user_id, status)两个索引

1-例子

运行:

sql 复制代码
EXPLAIN SELECT * FROM orders WHERE status = 1;

结果为:

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE orders ALL 99520 10 Using where

分析:联合索引无法使用

2-分析

联合索引结构:

复制代码
(user_id, status)

索引的排序结构实际上是:

复制代码
user_id → status

可以理解为类似这样排序:

复制代码
user_id=1 status=0
user_id=1 status=1
user_id=1 status=2

user_id=2 status=0
user_id=2 status=1
user_id=2 status=2

所以索引查找必须:

复制代码
先确定 user_id
再确定 status

而你的 SQL:

复制代码
WHERE status = 1

缺少:

复制代码
user_id

数据库不知道从哪一段开始查找,因此:

复制代码
无法利用索引

于是优化器选择:

复制代码
全表扫描

执行计划变成:

复制代码
type: ALL

3-引出概念

联合索引:

复制代码
(user_id, status)

可使用的查询:

复制代码
WHERE user_id = 1
WHERE user_id = 1 AND status = 1

不可使用:

复制代码
WHERE status = 1

规则:

复制代码
必须从索引最左列开始使用

这就是:

复制代码
最左匹配原则

4-举例说明

4-1.联合索引的存储方式

假设你建了一个联合索引 (user_id, status, amount),它在底层的排序方式是

bash 复制代码
(user_id, status, amount)

也就是说,索引先按 user_id 排序,再在相同的 user_id 下按 status 排序,再在相同的 (user_id, status) 下按 amount 排序

4-2.最左匹配原则的含义

查询条件必须从联合索引的最左字段开始,才能利用索引

可以用到连续的前缀字段,但一旦中间断了,就不能继续往后匹配

举例说明:

  • WHERE user_id = 1 :能用索引,用到索引的第一列
  • WHERE user_id = 1 AND status = 1:能用索引,用到索引的前两列
  • WHERE user_id = 1 AND status = 1 AND amount = 100:能用索引,用到索引的三列
  • WHERE user_id = 1 AND amount = 100:这种能用到部分索引,只能吃到user_id这一列
  • WHERE status = 1:不能用索引,因为跳过了最左的 user_id
  • WHERE status = 1 AND amount = 100:也不能用索引,因为没有从最左的 user_id 开始

PS:这个和你写的sql条件的顺序不影响,你写的sql会被优化器会自动重排条件

sql 复制代码
SELECT * FROM orders WHERE status = 1 AND user_id = 1;
#status写在前,user_id写在后,依旧可以吃到(user_id, status, amount)索引

5-删除冗余索引

因为联合索引和最左匹配原则:

如果现在表里有一个(user_id)单列索引(user_id, status, amount)联合索引,那么这个(user_id)单列索引可以删除了,因为联合索引由user_id开头,完全能覆盖单列索引的功能

相关推荐
我不介意孤独8 分钟前
04-记忆系统为什么向量数据库不够用
数据库·人工智能·资源隔离·agent infra
kyriewen27 分钟前
前端性能优化:LCP 从 4s 到 0.9s 的 5 个核心手段(附配置代码)
前端·javascript·性能优化
AOwhisky30 分钟前
MySQL 学习笔记(第六期):MySQL 备份与恢复
运维·数据库·笔记·学习·mysql·云计算
qq21084629531 小时前
【数据库】TDengine 清理旧数据
数据库·oracle·tdengine
j_xxx404_1 小时前
MySQL表操作硬核解析:从 CREATE TABLE 到磁盘文件、ALTER TABLE 与 DDL 风险
运维·服务器·数据库·c++·mysql·adb·ai
数据库小学妹1 小时前
PostgreSQL迁移到国产数据库怎么做?评估、改造、上线全流程实操指南
数据库·经验分享·postgresql·dba
Fanta丶1 小时前
19.Mysql覆盖索引、前缀索引
mysql
x***r1512 小时前
Redis Desktop Manager 0.8.8 安装教程(Windows redis-desktop-manager-0.8.8.384详细步骤)
数据库·windows·redis
initialize13062 小时前
Postgresql(Oracle兼容) 到Oracle19.9字符语义
数据库·oracle
梦想的旅途22 小时前
企业微信API实现外部群消息异步推送的技术架构与实践
mysql·架构·企业微信