insertinto t values (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3); 下面这两条语句是为了测试场景1中,能出现跳跃索引扫描 INSERTINTO t SELECT a, b + 5FROM t; INSERTINTO t SELECT a, b + 10FROM t;
场景1where条件后只带有组合索引的第二个字段
1 2 3 4 5 6 7
root@localhost:mysql-8.0-3319.sock 16:26:33 [dhy]> explain select a,b from t where b = 2; +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+----------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+----------------------------------------+ | 1 | SIMPLE | t | NULL | range | idx_a_b | idx_a_b | 10 | NULL | 3 | 100.00 | Using where; Using index for skip scan | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+----------------------------------------+ 1 row inset, 1 warning (0.00 sec)
从执行计划中可以看到,key这列显示使用到索引,同时key_ley的长度是10,也就是使用到了组合索引的所有字段,Extra中显示走了跳跃索引扫描(Using index for skip scan),如果是8.0以下的版本则不会出现跳跃索引,而是索引全表扫描。 这里执行时的流程应该是如下发生:
获取组合索引中,第一列去重之后的第一个值(本例子中就是a=1)
根据此值与组合索引中的第二列构成一个查询条件(a=1 and b = 2)
执行查询
获取组合索引中,第一列去重之后的第二个值(本例子中就是a=2)
根据此值与组合索引中的第二列构成一个查询条件(a=2 and b = 2)
执行查询
反复按以上规则执行,直到第一列去重之后的值全部扫描完成
场景2where条件后第一列是范围查询
1 2 3 4 5 6 7
mysql> explain select * from t where a > 1 and b = 2; +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t | NULL | range | idx_a_b | idx_a_b | 5 | NULL | 6 | 11.11 | Using where; Using index | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+ 1 row inset, 1 warning (0.00 sec)
oot@localhost:mysql-8.0-3319.sock 22:07:57 [dhy]>explain format=tree select * from t where a > 1 order by b ; +---------------------------------------------------------------------------------------+ | EXPLAIN | +---------------------------------------------------------------------------------------+ | -> Sort: t.b -> Filter: (t.a > 1) -> Index range scan on t using idx_a_b | +---------------------------------------------------------------------------------------+ 1 row inset (0.00 sec)
先根据索引做范围查询,过滤掉不满足条件(a>1)的数据,然后在根据b字段排序
场景3where条件后第一列是等值查询
1 2 3 4 5 6 7
mysql> explain select * from t where a =1 and b = 2 ; +----+-------------+-------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+ | 1 | SIMPLE | t | NULL | ref | idx_a_b | idx_a_b | 10 | const,const | 1 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+ 1 row inset, 1 warning (0.00 sec)