MySQL索引的最左前缀匹配原则是什么?

MySQL索引的最左前缀匹配原则是什么?

编码文章call10242025-02-01 3:22:4311A+A-

MySQL的索引的最左前缀匹配原则是指在我们使用复合索引的时候,查询的条件必须从索引的最左侧开始匹配,并且不能跳过某些列,具体来说就是指在一个表上存在一个复合索引的时候,那么查询的条件应该按照索引的列的顺序逐一进行匹配,也就是从最左的列开始,如果在查询中跳过了某个列,那么这个复合索引查询的优化条件就是没有用的,或者说必须要在该列上添加某个额外条件才能使得查询优化有效。如下所示。

CREATE INDEX idx_name ON table_name (col1, col2, col3);

假设存在上面这样一个复合索引操作,其索引的顺序是 (col1, col2, col3)。按照上面我们介绍的最左前缀匹配原则来讲,可以使用这个索引顺序查询的条件如下所示。

SELECT * FROM table_name WHERE col1 = 'value1';
SELECT * FROM table_name WHERE col1 = 'value1' AND col2 = 'value2';
SELECT * FROM table_name WHERE col1 = 'value1' AND col2 = 'value2' AND col3 = 'value3';

但是像是下面这个查询就不能完全使用这个索引操作,如下所示。

SELECT * FROM table_name WHERE col2 = 'value2'; (没有使用 col1,违反了最左前缀匹配)
SELECT * FROM table_name WHERE col2 = 'value2' AND col3 = 'value3'; (没有使用 col1,也违反了最左前缀匹配)

如果在查询中,只用到了索引的部分列,例如上面只用到了col2那么这个符合索引就不能被有效利用,除非是该列式单独索引的一部分,也就是说出了上面的索引之外,还有一个索引是col2列的索引。

所以在使用设计符合索引的时候,需要考虑到查询过程中的常用到的过滤列,并且保证它能够出现在索引的最左侧。

最左前缀匹配原则原理

其实不用想大家也知道,这个既然涉及到索引,那么可能和底层索引结构有关,首先我们知道,MySQL中最常见的索引类型就是B+树索引,它的每个树节点都包含有若干的键值,也就是Key值,并且这些Key值都是有序排列的,而在叶子结点中包含了索引列的值以及对应行的指针,这个指针指向的就是数据表中的数据行,在非叶子节点中,只包含数据结构不包含实际数据,并且在B+树中的每一层的数据都是保持平衡的,因此查找、插入、删除等操作的时间复杂度都是O(logN)。

而对于符合索引结构的存储,MySQL中会在B+树结构中存储多个列的值,假设上面提到的复合索引(col1, col2, col3),在MySQL存储索引的时候会按照(col1, col2, col3)的顺序存储对应的值。这个时候在叶子结点存储存储的就是每行的(col1, col2, col3)数据组合值以及对应行的指针,这个行指针指向了表中的数据。而在非叶子结点中只存储了索引的前缀值,并且这些值都是按照顺序进行排列的,例如索引中非叶子结点存储的只有col1或者是(col1, col2)的组合值。

这个时候,MySQL在执行索引查询的时候,查询条件会按照B+树索引的最左列进行逐步的匹配,这匹配过程就是按照B+树的结构进行匹配的,如下所示。

例如上面的复合索引(col1, col2, col3),在B+树的叶子节点中存储的是(col1, col2, col3)的组合数据,而在查询条件中的列是需要按照B+树中列的顺序进行匹配,所以下面这个查询。

SELECT * FROM table_name WHERE col1 = 'value1' AND col2 = 'value2';

当匹配第一列col1的时候,B+树会先根据col1的值找到对应的节点,如果在查询条件中没有col1的条件,B+树显然就不会知道从哪个节点开始查找,所以也就无法利用这个节点。

当匹配第二列col2的时候,如果查询条件中有col1,那么就可以继续尝试匹配col2,这个时候B+树的结构就会根据col2来进一步的缩小范围。

当匹配第三列col3的时候,如果查询条件中还有col3,那么就可以继续匹配,最终直接确定数据的位置。

也就是说,这整个的匹配过程是遵循了B+树的结构,并且每个列对应的应该是索引树的某个层次级别,因此可以有效的利用索引,如果不是最左前缀匹配的话,那么第一个节点就找不到,也就不知道如何利用下面的节点。

跳过列的情况

如果在查询过程中,跳过了某个列,如下所示。

SELECT * FROM table_name WHERE col2 = 'value2';

如果是这种情况,那么MySQL就无法从col1开始进行匹配,只能是跳过第一个列直接找col2这个列,这个时候,对于复合索引的优化也就无法生效了,因为在B+树的结构中就是按照(col1, col2, col3)列的顺序进行存储的,如果跳过了第一个col1的列,那么就MySQL就无法通过col1这个前缀来进行索引优化了。例如可能会出现如下的一些问题。

  • MySQL无法使用最左侧的 col1 索引进行查找,因此无法加速查询过程。
  • 对于复合索引 (col1, col2, col3),只有当查询条件涉及到 col1 或者 col1col2 组合时,才可能有效利用该索引。

索引覆盖扫描

如果查询只涉及到复合索引中的列,如下所示

 SELECT col1, col2 FROM table_name WHERE col1 = 'value1' AND col2 = 'value2';

在这个查询条件中,只包含了索引列所包含的字段,那么这个时候,MySQL会直接利用索引结果来进行结果获取,就不需要进行回表查询。这种情况下,查询优化器会使用复合索引 (col1, col2) 来进行匹配,并通过索引直接返回结果,避免了对表的访问,提高了性能。

其实上面这个问题MySQL会根据查询优化器来选择合适的索引,如果查询条件中能够按照最左前缀匹配原则从复合索引中进行匹配的话,那么优化器就会优先决定使用复合索引优化来进行查询,否则优化器可能会选择其他的索引,或者是对全表进行扫描,例如如果上面的操作中col2设置了单列索引,那么在走复合索引不生效的情况下,就会尝试通过col2的单列索引进行匹配。

总结

所以在MySQL中的最左前缀匹配原则是基于B+树索引的结构制定的,要求查询条件必须从索引的最左侧开始匹配,且不能跳过某些列。因为B+树的结构和索引的设计顺序决定了查询优化的效率,因此合理设计复合索引,充分利用最左前缀匹配原则,可以显著提升查询性能。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4