MySQL使用索引优化
来源:SegmentFault
时间:2023-02-16 15:27:24 160浏览 收藏
哈喽!今天心血来潮给大家带来了《MySQL使用索引优化》,想必大家应该对数据库都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到MySQL,若是你正在学习数据库,千万别错过这篇文章~希望能帮助到你!
一、概述
1.1大致目的
- 对Mysql存储引擎使用的索引有一个更加深入的理解。
- 对Mysql使用索引进行排序来优化查询有个大致了解。
- 理解覆盖索引和前缀索引。
- 理解联合索引,并能判断选择语句的执行是否使用了索引。
1.2explain关键字
explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在select语句前加上explain就可以了,本文将大量使用explain关键字,如果不熟悉它结果中的字段信息,可以参考MySQL官方文档:
MySQL官方对explain的使用说明
二、对单列的索引查找
2.1排序方式
mysql可以通过两种方式生成有序的结果:
- 通过排序操作
- 按照索引顺序扫描数据
由于mysql引擎如默认的Innodb底层使用的是B+树这种索引,所以使用索引扫描来进行排序是很快的。但是想要通过索引扫描的方式来优化排序是有很多限制条件的。
2.2本文建表
我们通过实例来说明什么是联合索引,首先我们先讨论对表单列的索引的情形。
我们使用的测试数据库含两个表,分别叫做:mytest_innodb、mytest_MyISAM,以下为见表语句:
使用InnoDB 创建的表
CREATE TABLE `mytest_innodb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `country` varchar(255) NOT NULL, `address` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `height`int(11) NOT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;
使用MyISAM存储引擎创建的表
CREATE TABLE `mytest_myisam` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `country` varchar(255) NOT NULL, `address` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `height`int(11) NOT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM;
我们对两个表填入相同的数据,保证两表除了引擎不同外,其他的表结构、表的内容全部一致,表的内容,结构如下:
下图为两个表的结构:
下图为两张表的信息(一样):
我们在建立两个没有主键的表,即分别对上面见表语句将 PRIMARY KEY (
id)去掉,名字命名为no_prikey_inno和no_prikey_mysi。
我们从表的结构知道,我们未设置其他索引。事实上,此时数据库表文件中会存储这关于主键的B+树索引,我们有如下测试:
2.3Innodb下的分析
我们先对Innodb引擎进行分析:
由于Innodb引擎是聚集引擎,它的索引和数据是存储在一起的,对于该表若有主键,则底层IBD文件中必定存放着关于主键的B+树索引,并且该课B+树的叶子节点会存放对应主键所对应的所有字段信息。
根据以上信息我们分析上述查询结果:
①在Innodb引擎下,对没有主键的表不管用什么方式(创建表后不再添加索引的情况下)查询,查询方式均不会使用索引。
②在Innodb引擎下,对于有主键的表(创建表后不再添加索引的情况下),若是where查询,限制条件是关于主键的则会走索引,在where条件下限制条件不是主键,则查询用到索引。当我们使用Oreder by进行对主键的升降序后必定走索引,此时在用where限制任何字段均不影响,索引的使用,这是因为对于底层B+树来说,我们只要通过主键排序后(这会使用索引),就可以轻松查询带其他字段(叶子节点下面挂着所有字段)
2.3MyISAM下的分析
我们在对MyISAM引擎进行分析:
可以看到,在使用MyiSAM下,对于不适用主键的情况是和Innodb一致的,但是使用主键的情况下,MyiSAM只对id的查找有用索引。这是为什么呢?
这是由于MyiSAM是非聚集引擎,它将数据和索引分开存储了,这样对于在建完表后不加索引下,它的索引文件只存放索引,所以若查询索引之外的东西,必然会跨文件查找,会产生IO。
2.4底层文件分析
由于mysql是关系型数据库,这意味着数据的存储是在磁盘上的,所以我们有必要对其底层文件进行一定分析:
可以看出对于MyiSAM文件在有无主键下MYI文件会差了1KB这是因为该文件是存放索引的,在无主键下,该文件下就无索引,必定会比有索引的主键下的存储容量少。
而Innodb的ibd文件却看不出有无主键下存储容量的差别,这是由于该文件中还存放数据,对于大容量的数据字段,索引的大小真的是微不足道,这也使得使用索引的查询会更高效,速度会更快。
三、联合索引
3.1 建立主键外的索引
我们在上面已经讨论过单个基于主键的索引,还有一种单个索引是表中没有索引,我们建立一个索引,这个索引可以不是主键,这种情况和单个主键索引类似,在此不在说明了。
所以现在,我们开始讨论对多个字段建立索引,先考虑非联合索引下的多个索引。下面我们改变上述见表语句,通过ALTER语句增加索引。详细见下:
alter table mytest_innodb add key (age); alter table mytest_myisam add key (age);
新的两张表结构如下:
我们测试:
这里我们发现对于age的索引查找若是查找自己本身的字段或者index是使用索引的,但查找包含其他字段时就不会使用索引。
这是因为,对于其他的非主键添加索引,它形成的B+树索引的叶子节点里面只会存储索引(该索引字段本身作为B+树的索引)。
所以在我们使用age排序后的全部字段的查找是要进行Using filesoret的。
但是注意一个很重要的一点就是 age的B+树是如何和主键的这一棵“主B+树”联系到一起的呢?
如上图,注意上图和上上图第一个例子的区别:
在通过age排序后对于一个确定值的所有有关字段的查找是这样子的,先通过age这棵B+树寻找到要查询位置的age,并且这个叶子节点是存放着主键的索引,于是MySQL会通过该索引到“主B+树”上查找到该主键对应的所有信息。
对于MyISAM我们考虑下图的这种情况,
这是因为MyiSAM是索引和数据分开的且,age索引下并未存放id主键而是存放的是存放数据的地址。(myisam数据存在地址里,索引下面直接存地址,这也是为什么它的查早速度快的其中一个原因)
3.2联合索引的基本概念
首先,联合索引是指对表上的多个列进行索引。但这多个列的索引是有限制,有关联的,满足“最左原则”。
联合索引的创建方法与单个索引创建的方法一样,不同之处仅在于有多个索引列。
联合索引的内部结构
我们以 KEY idx_age_height为例子看下联合索引内部B+树的结构:
从本质上来说,联合索引也是一颗B+树,不同的是联合索引的键值的数量不是1,而是大于等于2,这取决于要联合的字段个数。我们如上图建立的联合索引是关于age和height的,键值是按照顺序排列的,这里我们不得不提到“最左原则”。
最左原则
在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,并且底层B+树的排序也是先从最左边开始依次往右按照优先级进行排序。
联合索引产生的若干个索引
联合索引的最左原则就是建立索引KEY union_index (a,b,c)时,等于建立了(a)、(a,b)、(a,b,c)三个索引,从形式上看就是索引向左侧聚集,所以叫做最左原则,因此最常用的条件应该放到联合索引的组左侧。
四、联合索引下的查询分析
前缀索引
覆盖索引
未写完
理论要掌握,实操不能落!以上关于《MySQL使用索引优化》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
471 收藏
-
222 收藏
-
199 收藏
-
466 收藏
-
211 收藏
-
377 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习