您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

MySQL中一些关于索引的知识点

时间:2019-08-03 15:51:49  来源:  作者:

什么是索引

索引是一种数据结构,其作用就是用来提高数据查询效率。比较常用的比喻就是将其类比为书籍的目录。通过目录可以精确的找到某一章节的内容所在页。

在数据量较小的时候使用索引其实也没有什么意义,即使没有索引需要一条一条遍历数据对于计算机来说也并不需要太多时间。而一旦数据量较大,要保证我们能正常的对外提供服务,保证用户使用体验那么索引就是必要的了。

索引类型

索引时一种数据结构,为了应对不同的场景会有多种实现。在MySQL中主要就是Hash索引和B+Tree。

Hash索引

hash相信大家应该都很熟悉,hash是一种key-value形式的数据结构。实现一般是数组+链表的结构,通过hash函数计算出key在数组中的位置,然后如果出现hash冲突就通过链表来解决(拉链法)。当然还有其他的解决hash冲突的方法。hash这种数据结构是很常用的,比如我们系统使用HashMap来构建热点数据缓存,存取效率很好。

hash结构存数据首先通过计算key的hash值来确定其在数组中的位置,如果有冲突就在该数组位置建一个链表。这样很明显有几个问题:

  • 即使是具有相同特征的key计算出来的位置可能相隔很远,连续查询效率低下。即不支持范围查询
  • hash索引存储的事计算得到的hash值和行指针,而不存储具体的行值,所以通过hash索引查询数据需要进行两次查询(首先查询行的位置,然后找到具体的数据)
  • hash索引查询数据的前提就是计算hash值,也就是要求key为一个能准确指向一条数据的key,所以对于like等一类的匹配查询是不支持的。

所以我们可以知道的是hash索引适用于快速选取某一行的数据。

B+Tree结构

从名字上看这明显是一种树结构,在大学期间数据结构的课本上树结构是必讲的。树结构是一种特别重要的数据结构,在很多地方都会使用到。

上面我们说到hash索引无法进行范围查询,在树结构中也有一种方便进行有序查询的结构--二叉搜索树。二叉搜索树的结构中要求父节点的值大于左孩子节点并且小于右孩子节点,如下图。

技术干货分享:MySQL中一些关于索引的知识点

 

上图中二叉树的查询的时间复杂度为O(log(n)),当然要保证O(log(n))的时间复杂度就需要保证二叉树时刻保持平衡。

而在MySQL索引中虽然也使用了树结构,但是并不是使用的二叉树。因为在数据库中数据最终都是存放在磁盘上的,而如果树的节点过多的话,那么在节点之间转移会花费较多的时间。在MySQL的实现中选择将更多内容放在同一个节点,对同一个节点的操作转入在内存中完成,减少在外存中节点之间转移的次数,以达到提高效率的目的。这就是B+Tree,在B+Tree的实现中一个三层的树结构就基本上可以满足我们几乎所有的需求了。

B-Tree

要了解B+Tree首先就得了解B-Tree,B-Tree是一种平衡树,这里的B指的是Balance而不是Binary,更确切的说B-Tree是一种多路平衡搜索树。

多路平衡搜索树如下图:

技术干货分享:MySQL中一些关于索引的知识点

 

这是一种2-3树,意思就是每个节点存有两个值,同时每个节点分支数为3,从上图中可以看出来着中结构很适合查询数据。每个节点的左子树的值都是小于当前节点中最小的值,中间的子树的值全都是在当前节点两个值的中间,而右子树的值全都大于当前节点的最大值。

比如我们要查找24这个值:

  1. 首先从根节点判断24在根节点(15,25)之间,所以左右子树排除,从中间查找。
  2. 然后找到中间子树的根节点(18,22),比较发现24大于该节点最大值,排除左子树和中间子树。
  3. 找到右子树,判断节点大值刚好等于24,查询结束

基于上面的流程可以总结B树的搜索:

  • 从根结点开始,对结点内的关键字(有序)序列进行二分查找。
  • 如果命中则结束,否则进入查询关键字所属范围的子结点;
  • 重复上面的流程,直到所对应的子节点为空,或已经是叶子结点;

可以看出其搜索性能相当于在关键字集合内做一次二分查找。从这里看来好像B-Tree没有什么问题,但是需要注意到的是在B-Tree中每一个节点都是存储索引关键字以及其代表的具体行数据。而在MySQL中数据库加载数据是以页为单位加载,每一页的大小是固定的(默认16k)。如果每一个节点都存储所有的值,那么一页中能存下的节点就会很少,一次查询可能就会进行多次从内存中去加载数据,导致性能降低。

技术干货分享:MySQL中一些关于索引的知识点

 

B+Tree

B+Tree是对B-Tree的一个变种,让其更加适应于进行外部存储文件索引。

两者之前最大的不同就在于B-Tree的每个节点都存储所有的数据,而B+Tree需要存储的数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都有指向下一个相邻的叶子节点的地址。这样的结构保证了在一个内存页中可以存下更多的索引节点,并且更加适合进行范围查询。

索引

因为存储引擎负责实现索引,所以接下来讨论索引都是基于MySQL的InnoDB引擎。

聚簇索引

聚簇的意思是表示数据行和相邻的键值聚簇的存储在一起。一些数据库允许选择具体的某一个索引作为聚簇索引,而在InnoDB的实现中直接将主键索引指定为聚簇索引。如果没有定义主键,InnoDB 会选择一个唯一的非空索引来代替主键索引。如果同样没有定义这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引(row_id)。

聚簇索引实例如图:

技术干货分享:MySQL中一些关于索引的知识点

 

非聚簇索引索引

在InnoDB中除主键索引外其他都是非聚簇索引,所以也叫非主键索引。非主键索引的叶节点并不是存储一行的值,而是存储具体行的主键值。不满足聚簇的定义。

非聚簇索引实例如图:

技术干货分享:MySQL中一些关于索引的知识点

 

聚簇索引和非聚簇索引在查询时的差异

由上面的两种索引实例图就可以看出来,在查询时如果是通过主键索引查询的话直接查询到数据行然后返回。但是如果是通过非主键索引查询的话首先需要通过该索引确定主键,然后通过得到的主键从主键索引中查到具体行的数据,后面的通过得到的主键从主键索引中获取数据的过程被称为回表。

回表的过程使得通过普通索引查询较主键索引查询多了一步,在很多情况下效率相对较低。所以在我们的查询过程中如果能够仅通过主键确定数据那最好就是直接使用主键进行查询。

覆盖索引

上面介绍了通过非主键查询会有一个回表的过程,但是需要注意的是并不是每一个查询都存在回表这一步,对于一个普通索引来说其叶节点存储的是主键的值,那么假设我现在需要的数据也仅仅就是主键的值呢?通过普通索引取到主键的值后就并不需要再到主键索引中查,那么也就不存在回表这一过程了。

上面例子中该非主键索引已经存在了我们所需要的值,所以该索引也被称为覆盖索引。覆盖索引并不是一个固定的结构,可以使单索引(一个字段的索引),也可以使复合索引,凡是能够直接提供查询结果而不需要进行回表过程的都可以被称为覆盖索引。

很多时候我们不可能仅仅通过主键来确定数据,使用普通索引可能会导致低效,所以覆盖索引在日常开发过程中也是一个很常用的性能优化的手段。

当然覆盖索引页并不都是好的,比如我现在建立了一个索引index(a,b)。由a,b两个字段来建立索引,好处已经说过了就是查询ab字段时不会回表,但是如果仅仅通过b字段来查询就无法走这个索引了。建立的索引的索引项是按照索引定义里面出现的字段顺序排序的。

最左前缀原则

假设现在存在索引index(a,b),那么如果通过a和b来查询能够应用该索引,单独使用a来查询也能应用到该索引,但是如果单独使用b来查询则无法应用到该索引。这就是最左前缀原则,在匹配索引时回匹配索引最左边的n个字段,能匹配上就可以应用该索引。

由于最左前缀原则的存在也就要求我们在建立索引时可能需要考虑更多的事情。

首先需要清楚的事索引是一种数据结构,建立索引时需要消耗存储空间的,所以索引并不是建立的越多越好,而是应该根据需求尽可能的减少索引的数量。

而最左前缀原则的存在就使得一个联合索引可以被当成多个索引来使用,当然前提是设计好索引中字段的顺序(实际上最左前缀原则也并不是仅仅适用于联合索引,对于字符串索引也使用,字符串索引中最左n个字符相当于联合索引中的最左n个字段)。

比如index(a,b),有了这个索引后我们就不需要单独为a建立索引,所以在设计联合索引时一般将使用频率较高的字段放在前面。

然后是将区分度较高的字段靠前,区分度就是字段中值的重复率,重复率越低区分度越高。比如性别就不适合作为索引,区分度越高的字段经过一次筛选能过滤掉更多的行。

然后还需要考虑的是字段的大小,由于索引也需要占据空间所以一般选用较小的字段。



Tags:MySQL 索引   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
什么是索引?索引是数据库快速找到记录行的一种数据结构,类似我们看书时的目录,它是良好性能的关键因素。尤其是表中的数据量越来越大时,如果索引使用不当,会严重影响性能。索引也...【详细内容】
2021-02-25  Tags: MySQL 索引  点击:(189)  评论:(0)  加入收藏
在冯小刚冯导作为导演拍摄的《天下无贼》中有一句经典台词,那就是出自葛优之口:21世纪什么最贵?人才!从这句话说出到现在,已经16年过去了,那么在现在这个大数据时代,什么最贵呢?那...【详细内容】
2020-12-30  Tags: MySQL 索引  点击:(131)  评论:(0)  加入收藏
一、高性能索引1、查询性能问题在MySQL使用的过程中,所谓的性能问题,在大部分的场景下都是指查询的性能,导致查询缓慢的根本原因是数据量的不断变大,解决查询性能的最常见手段是...【详细内容】
2020-08-03  Tags: MySQL 索引  点击:(62)  评论:(0)  加入收藏
概述随着电商的发展,使用数据库的业务越来越复杂,除了掌握哪些场景可以使用索引,哪些场景适合使用索引,还需要掌握索引在运行过程中的一些使用规则,特别是组合索引的使用。比如索...【详细内容】
2020-07-06  Tags: MySQL 索引  点击:(54)  评论:(0)  加入收藏
一个索引提高600倍查询速度?首先准备一张books表create table books( id int not null primary key auto_increment, name varchar(255) not null, author varchar(...【详细内容】
2020-04-07  Tags: MySQL 索引  点击:(74)  评论:(0)  加入收藏
我会谈谈对于索引结构我自己的看法,以及分享如何从零开始一层一层向上最终理解索引结构。从一个简单的表开始createtableuser(idintprimarykey,ageint,heightint,weightint...【详细内容】
2019-12-26  Tags: MySQL 索引  点击:(117)  评论:(0)  加入收藏
学习索引,主要是写出更快的sql,当我们写sql的时候,需要明确的知道sql为什么会走索引?为什么有些sql不走索引?sql会走那些索引,为什么会这么走?我们需要了解其原理,了解内部具体过程,...【详细内容】
2019-12-24  Tags: MySQL 索引  点击:(75)  评论:(0)  加入收藏
前言为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字段的意义。助你了...【详细内容】
2019-10-29  Tags: MySQL 索引  点击:(101)  评论:(0)  加入收藏
索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),它们 包含着对数据表里所有记录的引用指针。普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是...【详细内容】
2019-10-11  Tags: MySQL 索引  点击:(180)  评论:(0)  加入收藏
MySQL凭借着出色的性能、低廉的成本、丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库。虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程...【详细内容】
2019-09-12  Tags: MySQL 索引  点击:(131)  评论:(0)  加入收藏
▌简易百科推荐
作者:雷文霆 爱可生华东交付服务部 DBA 成员,主要负责Mysql故障处理及相关技术支持。爱好看书,电影。座右铭,每一个不曾起舞的日子,都是对生命的辜负。 本文来源:原创投稿 *爱可生...【详细内容】
2021-12-24  爱可生    Tags:MySQL   点击:(7)  评论:(0)  加入收藏
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章...【详细内容】
2021-12-14  python数据分析    Tags:MySQL记录锁   点击:(18)  评论:(0)  加入收藏
binlog 基本认识 MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二...【详细内容】
2021-12-14  linux上的码农    Tags:mysql   点击:(13)  评论:(0)  加入收藏
为查询优化你的查询 大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查...【详细内容】
2021-12-09  元宇宙iwemeta    Tags:mysql   点击:(15)  评论:(0)  加入收藏
测试的目的和原因,公司有很多程序员,每个程序员对数据库和表结构都有自己的理解。而且每个程序员的理解往往是以效率考虑。既然都是为了效率考虑,那么我就来测试一下究竟哪种使...【详细内容】
2021-12-08  吴彬的分享    Tags:Mysql数据库   点击:(14)  评论:(0)  加入收藏
当你们考虑项目并发的时候,我在部署环境,当你们在纠结使用ArrayList还是LinkedArrayList的时候,我还是在部署环境。所以啊,技术不止境,我在部环境。今天这篇文章缕一下在同一台服...【详细内容】
2021-12-08  秃头码哥    Tags:MySQL数据库   点击:(17)  评论:(0)  加入收藏
对于数据分析来说,MySQL使用最多的是查询,比如对数据进行排序、分组、去重、汇总及字符串匹配等,如果查询的数据涉及多个表,还需要要对表进行连接,本文就来说说MySQL中常用的查询...【详细内容】
2021-12-06  笨鸟学数据分析    Tags:MySQL   点击:(21)  评论:(0)  加入收藏
在学习SQL语句之前,首先需要区分几个概念,我们常说的数据库是指数据库软件,例如MySQL、Oracle、SQL Server等,而本文提到的数据库是指数据库软件中的一个个用于存储数据的容器。...【详细内容】
2021-11-24  笨鸟学数据分析    Tags:SQL语句   点击:(23)  评论:(0)  加入收藏
概述以前参加过一个库存系统,由于其业务复杂性,搞了很多个应用来支撑。这样的话一份库存数据就有可能同时有多个应用来修改库存数据。比如说,有定时任务域xx.cron,和SystemA域...【详细内容】
2021-11-05  Java云海    Tags:分布式锁   点击:(31)  评论:(0)  加入收藏
MySQL的进阶查询 一、 按关键字排序 使用ORDERBY语句来实现排序排序可针对一个或多个字段ASC:升序,默认排序方式 【升序是从小到大】DESC:降序 【降序是从大到小】ORDER BY的...【详细内容】
2021-11-05  Java热点    Tags:SQL语句   点击:(28)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条