是什么
最左前缀匹配原则指的是在使用联合索引时,查询条件必须从索引的最左侧开始匹配,如果一个联合索引包括多个列,则查询条件必须包含第一个列的条件,然后是第二个,以此类推。
为什么
联合索引在B+树中的排序方式按照“从左到右”的顺序,例如联合索引(A,B,C)会按照(A,B,C)的顺序在B+树中进行排序。MySQL在查询时会优先使用A作为匹配依据,然后依次使用B和C。因此联合索引能够从左到右依次高效匹配,跳过最左侧字段会导致无法利用该索引。
注意点
范围查询遇到(>、<),就是停止匹配,例如 where a>1, b=2, c=3; a可以用上索引,但是b和c因为a经过范围查询,得到的数据是无序的,因此无法利用索引;但是遇到(>=、<=、between、前缀like),不会停止匹配。因为这些查询包含一个等值,可以直接定位到具体数据,然后往后扫描即可。
MySQL8的一个查询优化
Skip Scan
CREATE TABLE `t1` (
`f1` int NOT NULL AUTO_INCREMENT,
`f2` int NOT NULL,
`f3` int NOT NULL,
PRIMARY KEY (`f1`),
KEY `idx_f2_f3` (`f2`,`f3`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
INSERT INTO t1 (f2,f3) VALUES
(1,1), (1,2), (1,3), (1,4), (1,5),
(2,1), (2,2), (2,3), (2,4), (2,5);
INSERT INTO t1(f2,f3) SELECT f2, f3 + 5 FROM t1;
INSERT INTO t1(f2,f3) SELECT f2, f3 + 10 FROM t1;
INSERT INTO t1(f2,f3) SELECT f2, f3 + 20 FROM t1;
INSERT INTO t1(f2,f3) SELECT f2, f3 + 40 FROM t1;
where f3=1;
MySQL8之前进行查询是无法使用索引的,但是在MySQL8之后进行查询,语句用上了范围扫描。
这是因为查询前先统计了f2的数据,一共就1和2两个值。然后将f2=1和f2=2拼接进查询条件中,之后使用最左匹配原则使用索引进行查询。但是如果f2的基数过多、查询语句中有group by或者distinct、查询跨表就会使skip scan失效。
