暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql复合索引

原创 江湖小虾米 2024-01-22
241

当索引由多个字段组成时,称为复合索引或组合索引。当where谓词条件包含非等值匹配的操作时,如>,< ,!= 等,索引中此字段之后的谓词条件将不会使用索引。

例如:索引abc_ck由字段(a,b,c)组成。谓词条件为where a=‘aaa’ and b>100 and c=‘ccc’

此查询a,b字段可以使用到索引,c字段无法使用索引。

在表emps的(gender,birth_date,first_name)字段上创建一个组合索引

mysql> create index gbn_ck on emps(gender,birth_date,first_name); Query OK, 0 rows affected (2.18 sec) Records: 0 Duplicates: 0 Warnings: 0

显示创建的索引

mysql> show indexes from emps; +-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | emps | 0 | PRIMARY | 1 | id | A | 299150 | NULL | NULL | | BTREE | | | YES | NULL | | emps | 1 | emp_no_uk | 1 | emp_no | A | 299150 | NULL | NULL | | BTREE | | | YES | NULL | | emps | 1 | gbn_ck | 1 | gender | A | 1 | NULL | NULL | | BTREE | | | YES | NULL | | emps | 1 | gbn_ck | 2 | birth_date | A | 9402 | NULL | NULL | | BTREE | | | YES | NULL | | emps | 1 | gbn_ck | 3 | first_name | A | 291233 | NULL | NULL | | BTREE | | | YES | NULL | +-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 5 rows in set (0.02 sec)

查看索引三个字段=值条件的执行计划

mysql> desc format=tree select * from emps where gender='F' and birth_date = '1964-06-02' and first_name = 'Bezalel'; +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | EXPLAIN | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | -> Index lookup on emps using gbn_ck (gender='F', birth_date=DATE'1964-06-02', first_name='Bezalel'), with index condition: (emps.gender = 'F') (cost=0.35 rows=1) | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) #using gbn_ck (gender='F', birth_date=DATE'1964-06-02', first_name='Bezalel') #表示查询用到了gbn_ck索引,括号中列出的是使用到了索引中的哪几个字段 #此查询使用了索引中的3个字段

查看索引三个字段中间字段为非=值匹配的执行计划

mysql> desc format=tree select * from emps where gender='F' and birth_date > '1964-06-02' and first_name = 'Bezalel'; +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | EXPLAIN | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | -> Index range scan on emps using gbn_ck over (gender = 'f' AND '1964-06-02' < birth_date), with index condition: ((emps.first_name = 'Bezalel') and (emps.gender = 'F') and (emps.birth_date > DATE'1964-06-02')) (cost=2706 rows=6013) | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) #gbn_ck over (gender = 'f' AND '1964-06-02' < birth_date) #表明使用到了gbn_ck所以,括号中只有前两个字段,说明只使用到了索引的前两个字段

查看未使用索引第一个字段=值匹配的执行计划

mysql> desc format=tree select * from emps where birth_date = '1964-06-02' and first_name = 'Bezalel'; +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | EXPLAIN | +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | -> Filter: ((emps.first_name = 'Bezalel') and (emps.birth_date = DATE'1964-06-02')) (cost=30163 rows=2992) -> Table scan on emps (cost=30163 rows=299150) | +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) #Table scan on emps #表明使用的是全表扫描

总结:

1.复合索引要满足最左前缀原则才能使用到索引,即不能忽略索引左边字段而单独使用后面的字段。
2.如果符合索引的字段where条件上有困难谓词,即使用了非=值匹配,则复合所以中此字段之后的字段不会用到索引。
3.执行计划中使用了复合索引的哪几个字段可以通过树形结构的执行计划查看。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论