为什么 MySQL 联合索引必须满足最左前缀原则?

坦白说,MySQL 复合索引确实很有趣。
想想这个B+树的东西,数据应该是按顺序存储的。
比如(A,B,C)的组合索引,在B+树中先按A排序,如果A相同则按B排序,最后按C排序。
就像排队一样,先来先服务,得遵守规则。

如果你检查的时候不包括最左边的那个,你就会有麻烦了。
例如,如果您检查 b=1 和 c=2 的位置,则这将不起作用。
因为必须先找到B+树。
如果找不到a,怎么直接找到b呢?不可能的。
你必须一张一张地扫描它们,效率很低。
这几乎和索引一样无用。

优化器不能盲目使用。
您可以调整 WHERE 子句的顺序,例如 WHERE b=1 AND a=2 ,或更改为 WHERE a=2 AND b=1 但最左边那一栏的东西是不能移动的。
为什么?由于B+树是按顺序存储的,所以必须从左到右检查,没有办法跳过。
如果允许跳转,那么每次都必须扫描整个表,那么为什么还要费心建立索引呢?直接查表就可以了。

所以最左前缀的规则是:必须包含最左列。
例如,对于索引(A,B,C),您可以简单地检查A=1 ,或者A=1 和B=2 ,两者都可以被索引。
但如果我们只检查 b=2 ,那是行不通的,但必须有。
也可以检查 a=1 和 c=3 ,但 b 在列索引中。
必须的,不然就没用了。

进行范围查询时应多加注意。
例如,当a=1 且b>2 且c=3 时,这是一个问题。
如果您检查范围 b>2 ,则 c 之后的列可能不起作用。
由于B+树的结构,你从A开始查找,找到B的范围,C列就不能继续使用索引了。

ORDER BY 或 GROUP BY 是相同的。
如果按A、B排序,则可以直接使用该索引,无需重新排序。
这很容易。

为什么优化器不自动调整顺序?这真的很简单。
索引的物理结构就是这样,无法更改。
如果盲目调整,就得重新计算,最后可能还是不做改变更好。
如果进行调整,则必须确保第一列匹配,否则您仍然需要扫描整个表。
这是相当痛苦的。

简而言之,最左前缀的原理是由B+树的结构决定的。
设计索引时,需要将最常用的术语放在左侧。
尽管优化器可以调整顺序,但它不能更改第一列。
只有理解了这一点,才能高效地使用索引。

一篇文章讲清楚MySQL的聚簇/联合/覆盖索引、回表、索引下推

结论:
1 .聚集索引:InnoDB索引叶子节点来存储行数据,主键默认是聚集的。
当没有主键时,MySQL会自动创建一个隐藏主键。
2 .非聚集索引:叶子节点存储索引字段和主键以节省空间,查询必须回溯到表才能找到完整的行。
3 、联合索引:对于多字段索引,必须指定顺序,以减少扫描的行数。
搜索字段的顺序必须与索引匹配。
4 、覆盖索引:查询字段在索引中,不需要返回表,提高了效率。
5 、查询回表:查询字段不在索引中。
必须先检查索引,然后再返回表,这增加了I/O开销。
6 .索引下推:MySQL 5 .6 中的一个特性,首先在索引级别进行过滤,以减少返回表的行数,提高效率。

mysql中聚集索引、辅助索引、覆盖索引、联合索引怎么用

我记得在那个项目中工作,我负责优化电子商务平台的数据库查询。
用户经常需要根据订单号查询订单详细信息。
orders表的主键是订单号,但是每次查询都需要扫描整个表,效率非常低。
所以我决定给序列表添加二级索引。

那天,我坐在办公室电脑前敲代码,心想添加辅助索引应该会大大提高查询效率。
果然,添加辅助索引后,订单号查询速度明显加快。

但是我也发现了一个问题。
某些情况下,用户需要同时根据订单号和订单状态查询订单。
在这种情况下,您将需要一个联合索引。
我尝试在订单号和订单状态上创建联接索引,但发现仅基于订单号运行查询可以显着提高性能。
但如果查询条件中包含订单状态,且该订单状态不是连接索引的第一列,则会降低查询效率。

现在我突然想到使用连接索引的规则说了一些关于“最左边前缀匹配”的内容。
可能有必要重新考虑指数设计。
等等,还有一件事:我好像记得覆盖索引可以减少IO操作,所以也许你可以尝试使用覆盖索引来进一步提高查询效率?