首页 > 数据库 >mysql学习(9):联合索引和多个单列索引的使用区别详解

mysql学习(9):联合索引和多个单列索引的使用区别详解

时间:2022-11-16 18:25:58浏览次数:74  
标签:索引 phone 查询 stu 详解 student mysql id

前言
为了提高数据库的查询效率,建索引是最常用的手段。那么问题来了,如果查询条件为2个及以上,我们是创建多个单列索引好呢,还是建一个联合索引比较好?

正文
我们首先来建一张表,并且指定其中的3个字段(学号、姓名、电话)为联合索引:

CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`stu_id` varchar(20) DEFAULT NULL COMMENT '学号',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`phone` varchar(30) DEFAULT NULL COMMENT '电话',
`address` varchar(30) DEFAULT NULL COMMENT '家庭住址',
PRIMARY KEY (`id`),
KEY `联合索引` (`stu_id`,`name`,`phone`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='学生表';
1
2
3
4
5
6
7
8
9
接下来我们使用Explain查询来查看接下来的SQL查询语句的执行计划,这次我们只关注key和key_len列。其中key列显示MySQL实际决定使用的索引,如果没有使用到索引则显示NULL。key_len列显示索引中使用的字节数。

一、联合索引验证
1、针对联合索引中的字段分别进行单个查询
1、针对索引字段stu_id进行查询,结果联合索引有效:

EXPLAIN
SELECT * from student where stu_id = '001';
1
2

2、针对索引字段name进行查询,结果联合索引无效:

EXPLAIN
SELECT * from student where name = '小明';
1
2

3、针对索引字段phone进行查询,结果联合索引无效:

EXPLAIN
SELECT * from student where phone = '123';
1
2


2、针对联合索引中的字段进行两两组合查询
1、对索引排列中的前两个(stu_id、name)进行查询,结果联合索引有效:

EXPLAIN
SELECT * from student where stu_id = '001' AND name= '小明';
1
2

2、对索引排列中的第一个和第三个(stu_id、phone)进行查询,结果联合索引有效:

EXPLAIN
SELECT * from student where stu_id = '004' AND phone = '14785454554';
1
2

3、在第2点的基础上,调换一下stu_id、phone的位置,结果联合索引仍有效:

EXPLAIN
SELECT * from student where phone = '14785454554' AND stu_id = '004';
1
2


4、对索引排列中的第二个和第三个(name、phone)进行查询,结果联合索引无效:

EXPLAIN
SELECT * from student where stu_id = '004' OR name = '小军';
1
2


3、针对联合索引中的字段进行全组合查询
1、按照索引的定义顺序进行查询,结果联合索引有效:

EXPLAIN
SELECT * from student where stu_id = '004' AND name = '小明' AND phone = '123';
1
2

2、打乱3个查询条件的顺序,结果联合索引仍有效:

EXPLAIN
SELECT * from student where phone = '123' AND name = '小明' AND stu_id = '004';
1
2

3、如果where条件出现OR,结果联合索引无效:

EXPLAIN
SELECT * from student where phone = '123' AND name = '小明' OR stu_id = '004';
1
2


二、多个单列索引验证
1、联合索引和单列索引同时存在
再分别对那3个字段建一个索引,同时保留联合索引:

create index index_stu_id on student(stu_id);
create index index_name on student(name);
create index index_phone on student(phone);
1
2
3
1、再来查询单个字段stu_id,结果显示使用了联合索引:

EXPLAIN
SELECT * from student where stu_id = '004';
1
2

2、再来查单个字段phone,结果使用了单例索引:

EXPLAIN
SELECT * from student where phone = '14785454554';
1
2

其实这里涉及到了mysql优化器的优化策略,当有多种索引存在时,优化器会评估哪个条件的索引效率最高,它会选择最佳的索引去使用。

2、只有单列索引
现在去掉联合索引,只剩下3个单列索引,再来进行查询

drop index 联合索引 on student;
1
1、单个字段查询,结果使用了对应字段的索引:

EXPLAIN
SELECT * from student where phone = '123';
1
2

2、多个字段查询,结果使用的是优化器选择出来的索引:

EXPLAIN
SELECT * from student where phone = '123' AND stu_id = '004';
1
2

3、多个字段查询,where条件使用OR,结果索引失效:

EXPLAIN
SELECT * from student where phone = '123' AND name = '小明' OR stu_id = '004';
1
2


总结
利用联合索引,我们可以缩小搜索的范围。但是使用联合索引不同于使用多个单独的索引。联合索引的结构其实与通讯录类似,人的名字由姓氏和名字组成,通讯录通常首先按照姓氏进行排序,然后按名字对有相同姓氏的人进行排序。如果我们知道姓氏,那么通过通讯录查找将会很有用;如果我们同时知道姓氏和名字,那么查通讯录会更加有效;但是如果我们只知道姓名,不知道姓氏,那么通讯录将没有用处。

所以我们在创建联合索引时,应该仔细考虑下列的顺序。对索引中的所有列执行查询,或者对前几列进行查询,联合索引将会非常有效;但是仅对后面的任意列进行搜索时,联合索引将没有用处。

多个单列索引在多个条件查询时,优化器会选择最优索引策列,可能只会用到其中一个索引,也可能用到多个索引。但是多个单列索引底层会建立多个B树索引,比较占用空间,也会浪费一定的搜索效率,所以只要有多个条件的联合查询,最好时建立联合索引。

最左前缀原则:
以索引定义的最左边为起点,任何连续的索引都能匹配上,
注:如果第一个字段是范围查询,则需要单独建一个索引。
注:在创建联合索引时,要根据业务的要求,where子句中使用最频繁的一列放在最左边。这样的扩展性比较好,比如stu_id经常作为查询条件,而phone不常用,则需要把stu_id放在联合索引的第一位,即最左边。

同时存在联合索引和单列索引(字段有重复)时,这时mysql查询会怎么使用索引呢?这个涉及到mysql本身的查询优化器策略了,当一个表有多条索引可以走时,mysql会根据查询语句的成本来选择走哪条索引。

联合索引的本质理解:
当创建了(a,b,c)这个联合索引时,相当于创建了下面这3条索引:
(a)这个单列索引;
(a,b)这个联合索引;
(a,b,c)这个联合索引。
想要索引生效的话,只能使用a,ab,abc这3种查询方式。上面我们测试过,ac组合也可以,但实际上只用到了a的索引,c并没有用到。
————————————————
版权声明:本文为CSDN博主「name_s_Jimmy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

参考:mysql学习(9):联合索引和多个单列索引的使用区别详解

标签:索引,phone,查询,stu,详解,student,mysql,id
From: https://www.cnblogs.com/aspirant/p/16896990.html

相关文章

  • 查看MySQL数据库所有的表名、表注释、字段名称、类型、长度、备注,一键导出生成数据库
    一、先了解下INFORMATION_SCHEMA1、在MySQL中,把INFORMATION_SCHEMA看作是一个数据库,确切说是信息数据库。其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据......
  • 表面粗糙度详解及参数对比表说明
    表面粗糙度详解及参数对比表说明来源https://zhuanlan.zhihu.com/p/115444210 表面粗糙度表面粗糙度(surfaceroughness)是指加工表面具有的较小间距和微小峰谷的不......
  • MySQL清空表提示Cannot truncate a table referenced in a foreign key constraint
    MySQL清空表提示Cannottruncateatablereferencedinaforeignkeyconstraint在MySQL执行truncatetablexxx时,出现了这个报错[Err]1701-Cannottruncateatable......
  • 彻底把 MySQL的锁搞懂
       最近,同事在生产上遇到一个MySQL死锁的问题,于是在帮忙解决问题后,特意花了一周的时间,把MySQL所有的锁都整理了一遍,今天就来一起聊聊MySQL锁。申明:本文基于M......
  • Pycharm“索引中”问题
    问题描述在Pycharm编辑器中进行训练模型时,如果导入包含数据集的项目后,后台便会有持续性任务进行中,称作是“索引中”。问题原因正是由于项目中数据集的存在,比如某个文件......
  • python 3.6下 安装mysqlclient
    倒腾了大半天,终于把mysqlclient安装成功,赶紧把步骤进行梳理并记录1、python安装好以后,首先要看一下自己的python是32还是64位的,这关系到你下载的mysqlclient。查看方法:......
  • 详解主成分分析PCA与奇异值分解SVD-降维后的矩阵components_ & inverse_transform【菜
    视频作者:[菜菜TsaiTsai]链接:[【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili]V(k,n)这个矩阵保存在.components_这个属性当中我们之前谈到......
  • 虚函数详解
    1定义定义:在某​​基类​​​中声明为virtual并在一个或多个​​​派生类​​​中被重新定义的​​​成员函数​​[1]语法:virtual函数返回类型函数名(......
  • MYSQL5.7 保姆级安装教程
    现在要是说mysql是什么东西,就不礼貌了虽然有的同学没有进行系统的深入学习,但应该也有个基本概念【不了解也没关系,后续会进行mysql专栏讲解】简单来说,存储数据的学习mysq......
  • 2-MySQL面试题
    数据库基础知识为什么要使用数据库数据保存在内存优点:存取速度快缺点:数据不能永久保存数据保存在文件优点:数据永久保存缺点:1)速度比内存操作慢,频繁的IO操作。2)查......