四时宝库

程序员的知识宝库

MySQL大厂面试题:没点硬实力还真搞不定,一文讲透联合索引


今日,无意间打开了脉脉,看到了一条某大厂的一面的关于数据库的面试题。点进去看了一眼


细想一下,感觉想要答得完美还是挺不容易的,于是就赶紧做了一番实验。验证一下自己的想法,同时记录一下。

问题

数据库中4个字段id,a,b,c。其中id主键,有两个联合索引,ab,ac下面几个查询都会用到哪些索引

select * from t where a=xx and b=xx and c=xx;

select * from t where a=xx and c=xx and b=xx;

select * from t where a=xx and (b=xx or b=xx);

问题看上去貌似挺简单的,但细想又觉得好像很难回答的很全面。

首先先放上我实验后的一些结论

结论

先说结论,再通过实验来证明

01 查询条件b和c的先后顺序,不影响最终的索引选择

02 ab,ac联合索引建立的先后顺序会影响索引的选择

03 MySQL优化器会根据possible_keys中的索引键顺序选取索引,如果能满足需求则不继续选择后面的索引。possible_keys内可以选取的索引键就是安装创建顺序排列的。

04 按顺序只选取possible_keys内的第一个索引的情况包括:abc三个字段都唯一、abc三个字段都不唯一、a唯一bc不唯一。

05 当只有b和c其中一个字段唯一时,会分别选取ab或ac的组合索引。

06 or会导致索引失效,因此只有a字段能用到索引,所以第三个是索引是用到了ac组合索引中的a

以上结论部分为个人理解,可能有不对的地方,希望大家留言讨论交流。

实验验证

先建两张表t1,t2,两张表的唯一区别就是建立联合索引的顺序不同。

t1 先建ab联合索引,再建ac联合索引

t2 先建ac联合索引,再建ab联合索引

一、先建立ab联合索引,再建立ac联合索引

  1. a b c 都唯一
mysql> select * from t1 where a=20 and b=20 and c=20;
+----+------+------+------+
| id | a | b | c |
+----+------+------+------+
| 20 | 20 | 20 | 20 |
+----+------+------+------+
mysql> explain select * from t1 where a=20 and b=20 and c=20;
+----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | ref | idx_ab,idx_ac | idx_ab | 10 | const,const | 1 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t1 where a=20 and c=20 and b=20;
+----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | ref | idx_ab,idx_ac | idx_ab | 10 | const,const | 1 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

根据explain的显示结果,交换where条件中b和c的位置,对索引的选取没有影响。最终选择了使用ab联合索引。

  1. a b c 不唯一

不唯一的情况分为四种:

a,b,c三者都不唯一

explain结果显示都使用了idx_ab索引

a,b不唯一,c唯一

explain显示优化器最后选择了idx_ac索引。

a,c不唯一,b唯一

explain显示优化器最终选择了idx_ab联合索引

a 唯一,b,c不唯一

选择了ab联合索引,与都不唯一的情况相同

小结

1、查询条件b和c的顺序,不影响最终的索引选择

2、只有当a,b字段不唯一,c字段唯一的情况下才会选择ac联合索引,其余情况都会选择ab联合索引


先建立ac联合索引,再建立ab联合索引

  1. a b c 都唯一

根据explain的显示结果,交换where条件中b和c的位置,对索引的选取没有影响。最终选择了使用ac联合索引。

  1. a b c 不唯一

不唯一的情况分为四种:

a,b,c三者都不唯一

explain显示只选择了ac联合索引

a,b不唯一,c唯一

explain显示选取了ac联合索引

a,c不唯一,b唯一

显示使用了ab联合索引

a唯一,bc不唯一

显示使用了ac联合索引

小结

1、查询条件b和c的位置,不影响最终的索引选择

2、只有当a,c字段不唯一,b字段唯一的情况下才会选择ab联合索引,其余情况都会选择ac联合索引

根据这两次实验,ab和ac组合索引的创建先后顺序不同,explain显示选择的索引键的不同,证实了之前的结论。


第三个sql

select * from t where a=xx and (b=xx or b=xx);

explain显示用到的索引键为idx_ac,key_len 为5个字节,a字段类型为int,占4个字节,字段允许为空,需要用1个字节来记录。因此这里or会导致索引失效,只有a字段用到了索引。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接