mysql聚集索引、辅助索引、覆盖索引、联合索引的使用


Posted in MySQL onFebruary 12, 2022

《MySQL技术内幕 InnoDB存储引擎》学习笔记

聚集索引(Clustered Index)

聚集索引就是按照每张表的主键构造一棵B+树,同时叶子节点中存放的即为整张表的行记录数据。

举个例子,直观感受下聚集索引。

创建表t,并以人为的方式让每个页只能存放两个行记录(不清楚怎么人为控制每页只存放两个行记录):

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

最后《MySQL技术内幕》的作者通过分析工具得到这棵聚集索引树的大致构造如下:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

聚集索引的叶子节点称为数据页,每个数据页通过一个双向链表来进行链接,而且数据页按照主键的顺序进行排列。

如图所示,每个数据页上存放的是完整的行记录,而在非数据页的索引页中,存放的仅仅是键值及指向数据页的偏移量,而不是一个完整的行记录。

如果定义了主键,InnoDB会自动使用主键来创建聚集索引。如果没有定义主键,InnoDB会选择一个唯一的非空索引代替主键。如果没有唯一的非空索引,InnoDB会隐式定义一个主键来作为聚集索引。

辅助索引(Secondary Index)

辅助索引,也叫非聚集索引。和聚集索引相比,叶子节点中并不包含行记录的全部数据。叶子节点除了包含键值以外,每个叶子节点的索引行还包含了一个书签(bookmark),该书签用来告诉InnoDB哪里可以找到与索引相对应的行数据。

还是以《MySQL技术内幕》中的例子,来直观感受下辅助索引的模样。

还是以上面的表t为例,在列c上创建非聚集索引:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

然后作者通过分析工作得到辅助索引和聚集索引的关系图:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

可以看到辅助索引idx_c的叶子节点中包含了列c的值和主键的值。

以Key为7fffffff为例,7是0111,0代表负数,真实的值应该取反加1,是-1,这是列c的值。Pointer是80000001,8是1000,1代表正数,所以80000001代表1,是主键的值。

覆盖索引(Covering index)

InnoDB存储引擎支持覆盖索引,即从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。

使用覆盖索引有啥好处?

  • 可以减少大量的IO操作

上图中我们知道,如果要查询辅助索引中不含有的字段,得先遍历辅助索引,再遍历聚集索引,而如果要查询的字段值在辅助索引上就有,就不用再查聚集索引了,这显然会减少IO操作。

比如上图中,以下sql可以直接使用辅助索引,

select a from where c = -2;
  • 有助于统计

假设存在如下表:

CREATE TABLE `student` (
  `id` bigint(20) NOT NULL,
  `name` varchar(255) NOT NULL,
  `age` varchar(255) NOT NULL,
  `school` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`),
  KEY `idx_school_age` (`school`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

如果在该表上执行:

select count(*) from student

优化器会怎么处理?

遍历聚集索引和辅助索引都可以统计出结果,但辅助索引要远小于聚集索引,所以优化器会选择辅助索引来统计。执行explain命令:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

key和Extra显示使用了idx_name这个辅助索引。

还有,假设执行以下sql:

select * from student where age > 10 and age < 15

因为联合索引idx_school_age的字段顺序是先school再age,按照age做条件查询,通常不走索引:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

但是,如果保持条件不变,查询所有字段改为查询条目数:

select count(*) from student where age > 10 and age < 15

优化器会选择这个联合索引:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

联合索引

联合索引是指对表上的多个列进行索引。

以下为创建联合索引idx_a_b的示例:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

联合索引的内部结构:

mysql聚集索引、辅助索引、覆盖索引、联合索引的使用

联合索引也是一棵B+树,其键值数量大于等于2。键值都是排序的,通过叶子节点可以逻辑上顺序的读出所有数据。数据(1,1)(1,2)(2,1)(2,4)(3,1)(3,2)是按照(a,b)先比较a再比较b的顺序排列。

基于上面的结构,对于以下查询显然是可以使用(a,b)这个联合索引的:

select * from table where a=xxx and b=xxx ;

select * from table where a=xxx;

但是对于下面的sql是不能使用这个联合索引的,因为叶子节点的b值,1,2,1,4,1,2显然不是排序的。

select * from table where b=xxx

联合索引的第二个好处是对第二个键值已经做了排序。举个例子:

create table buy_log(
    userid int not null,
    buy_date DATE
)ENGINE=InnoDB;

insert into buy_log values(1, '2009-01-01');
insert into buy_log values(2, '2009-02-01');

alter table buy_log add key(userid);
alter table buy_log add key(userid, buy_date);

当执行

select * from buy_log where user_id = 2;

时,优化器会选择key(userid);但是当执行以下sql:

select * from buy_log where user_id = 2 order by buy_date desc;

时,优化器会选择key(userid, buy_date),因为buy_date是在userid排序的基础上做的排序。

如果把key(userid,buy_date)删除掉,再执行:

select * from buy_log where user_id = 2 order by buy_date desc;

优化器会选择key(userid),但是对查询出来的结果会进行一次filesort,即按照buy_date重新排下序。所以联合索引的好处在于可以避免filesort排序。

到此这篇关于mysql聚集索引、辅助索引、覆盖索引、联合索引的使用的文章就介绍到这了,更多相关聚集索引、辅助索引、覆盖索引、联合索引内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
数据库的高级查询六:表连接查询:外连接(左外连接,右外连接,UNION关键字,连接中ON与WHERE的不同)
Apr 05 MySQL
MySQL 百万级数据的4种查询优化方式
Jun 07 MySQL
SQL之各种join小结详细讲解
Aug 04 MySQL
详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑
Dec 06 MySQL
JMeter对MySQL数据库进行压力测试的实现步骤
Jan 22 MySQL
解析MySQL索引的作用
Mar 03 MySQL
MySQL的存储函数与存储过程的区别解析
Apr 08 MySQL
排查并解决MySQL生产库内存使用率高的报警
Apr 11 MySQL
解决Mysql中的innoDB幻读问题
Apr 29 MySQL
MySQL中JOIN连接的基本用法实例
Jun 05 MySQL
MySQL导致索引失效的几种情况
Jun 25 MySQL
MySQL存储过程及语法详解
Aug 05 MySQL
详解MySql中InnoDB存储引擎中的各种锁
Mysql忘记密码解决方法
Mysql存储过程、触发器、事件调度器使用入门指南
Jan 22 #MySQL
MySQL数据库⾼可⽤HA实现小结
weblogic服务建立数据源连接测试更新mysql驱动包的问题及解决方法
Jan 22 #MySQL
解决Mysql多行子查询的使用及空值问题
Jan 22 #MySQL
如何避免mysql启动时错误及sock文件作用分析
Jan 22 #MySQL
You might like
php获取后台Job管理的实现代码
2011/06/10 PHP
PDO防注入原理分析以及使用PDO的注意事项总结
2014/10/23 PHP
PHP接收App端发送文件流的方法
2016/09/23 PHP
PHP Header失效的原因分析及解决方法
2016/11/16 PHP
解决php用mysql方式连接数据库出现Deprecated报错问题
2019/12/25 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
2020/02/18 PHP
一些经常会用到的Javascript检测函数
2010/05/31 Javascript
模拟电子签章盖章效果的jQuery插件源码
2013/06/24 Javascript
解析Jquery取得iframe中元素的几种方法
2013/07/04 Javascript
Javascript遍历Html Table示例(包括内容和属性值)
2014/07/08 Javascript
jquery删除指定子元素代码实例
2015/01/13 Javascript
浅谈jQuery中的事件
2015/03/23 Javascript
jQuery+css实现炫目的动态块漂移效果
2016/01/28 Javascript
jQuery解析与处理服务器端返回xml格式数据的方法详解
2016/07/04 Javascript
67 个节约开发时间的前端开发者的工具、库和资源
2017/09/12 Javascript
js+css实现打字效果
2020/06/24 Javascript
vue+axios+element ui 实现全局loading加载示例
2018/09/11 Javascript
使用 Vue cli 3.0 构建自定义组件库的方法
2019/04/30 Javascript
Vue使用Clipboard.JS在h5页面中复制内容实例详解
2019/09/03 Javascript
记录vue做微信自定义分享的一些问题
2019/09/12 Javascript
微信小程序 导入图标实现过程详解
2019/10/11 Javascript
基于JS正则表达式实现模板数据动态渲染(实现思路详解)
2020/03/07 Javascript
vue和小程序项目中使用iconfont的方法
2020/05/19 Javascript
vue-admin-template配置快捷导航的代码(标签导航栏)
2020/09/04 Javascript
pandas DataFrame数据转为list的方法
2018/04/11 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
Python中__repr__和__str__区别详解
2019/11/07 Python
keras小技巧——获取某一个网络层的输出方式
2020/05/23 Python
Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)
2020/03/18 HTML / CSS
Contém1g官网:巴西彩妆品牌
2020/01/17 全球购物
财务管理专业应届毕业生求职信
2013/09/22 职场文书
大学生村官典型材料
2014/01/12 职场文书
八一建军节感言
2014/02/28 职场文书
公司会计主管岗位责任制
2014/03/01 职场文书
安全资料员岗位职责范本
2014/06/28 职场文书
Apache Hudi 加速传统的批处理模式
2022/04/24 Servers