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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL中一些关于索引的知识点什么是索引索引是一种数据结构,其作用就是用来提高数据查询效率。比较常用的比喻就是将其类比为书籍的目录。通过目录可以精确的找到某一章节的内容所在页。在数据量较小的时候使用索引其实也没有什么意义,即使没有索引需要一条一条遍历数据对于计算机来说也并不需要太多时间。

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

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

索引类型
索引时一种数据结构,为了应对不同的场景会有多种实现。在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索引无法进行范围查询,在树结构中也有一种方便进行有序查询的结构--二叉搜索树。二叉搜索树的结构中要求父节点的值大于左孩子节点并且小于右孩子节点,如下图。

image

上图中二叉树的查询的时间复杂度为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是一种多路平衡搜索树。

多路平衡搜索树如下图:

image

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

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

首先从根节点判断24在根节点(15,25)之间,所以左右子树排除,从中间查找。
然后找到中间子树的根节点(18,22),比较发现24大于该节点最大值,排除左子树和中间子树。
找到右子树,判断节点大值刚好等于24,查询结束
基于上面的流程可以总结B树的搜索:

从根结点开始,对结点内的关键字(有序)序列进行二分查找。
如果命中则结束,否则进入查询关键字所属范围的子结点;
重复上面的流程,直到所对应的子节点为空,或已经是叶子结点;
可以看出其搜索性能相当于在关键字集合内做一次二分查找。从这里看来好像B-Tree没有什么问题,但是需要注意到的是在B-Tree中每一个节点都是存储索引关键字以及其代表的具体行数据。而在MySQL中数据库加载数据是以页为单位加载,每一页的大小是固定的(默认16k)。如果每一个节点都存储所有的值,那么一页中能存下的节点就会很少,一次查询可能就会进行多次从内存中去加载数据,导致性能降低。

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

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

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

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

聚簇索引实例如图:
image

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

非聚簇索引实例如图:
image

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

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

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

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

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

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

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

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

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

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

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

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

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

参考资料
MySQL运维内参:MySQL、Galera、Inception核心原理与最佳实践
原文地址https://www.cnblogs.com/liyus/p/11287173.html

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
25天前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
1月前
|
SQL 关系型数据库 MySQL
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
|
1月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
61 3
Mysql(4)—数据库索引
|
15天前
|
存储 Oracle 关系型数据库
[MySQL]知识点
本文详细介绍了MySQL中int族和char族数据类型的特点、存储范围及使用建议,以及text、blob类型和内置字符处理函数。文章强调了数据类型选择的重要性,并提供了多个实例帮助理解。
31 0
[MySQL]知识点
|
16天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
82 1
|
27天前
|
存储 关系型数据库 MySQL
如何在MySQL中进行索引的创建和管理?
【10月更文挑战第16天】如何在MySQL中进行索引的创建和管理?
56 1
|
17天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
28天前
|
监控 关系型数据库 MySQL
mysql8索引优化
综上所述,深入理解和有效实施这些索引优化策略,是解锁MySQL 8.0数据库高性能查询的关键。
29 0
|
1月前
|
SQL 关系型数据库 MySQL
美团面试:mysql 索引失效?怎么解决? (重点知识,建议收藏,读10遍+)
本文详细解析了MySQL索引失效的多种场景及解决方法,包括破坏最左匹配原则、索引覆盖原则、前缀匹配原则、`ORDER BY`排序不当、`OR`关键字使用不当、索引列上有计算或函数、使用`NOT IN`和`NOT EXISTS`不当、列的比对等。通过实例演示和`EXPLAIN`命令分析,帮助读者深入理解索引失效的原因,并提供相应的优化建议。文章还推荐了《尼恩Java面试宝典》等资源,助力面试者提升技术水平,顺利通过面试。
|
1月前
|
关系型数据库 MySQL 数据库
深入浅出MySQL索引优化:提升数据库性能的关键
在这个数据驱动的时代,数据库性能的优劣直接关系到应用的响应速度和用户体验。MySQL作为广泛使用的数据库之一,其索引优化是提升查询性能的关键。本文将带你一探MySQL索引的内部机制,分析索引的类型及其适用场景,并通过实际案例演示如何诊断和优化索引,以实现数据库性能的飞跃。