当前位置: 首页 > ops >正文

MySQL的索引(索引的数据结构-B+树索引):

目录

索引的基本概念:

优点:

缺点:

B+树索引:

聚簇索引:

特点:

优点:

缺点:

非聚簇索引:

聚簇索引与非聚簇索引的区别:

InnoDB存储引擎:

MyISAM存储引擎:

InnoDB与MyISAM的区别:

总结(B+树执行的流程):


索引的基本概念:

索引是存储引擎用于快速找到数据记录的一种数据结构,在进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据,如果不符合则需要全表扫描,也就是需要一条一条查找记录,直到找到条件符合的记录。索引的目的就是为了减少磁盘的I/O次数,加快查询速率。

可以理解为“排好序的快速查找数据结构”,以某种方式指向数据,就能在此基础上实现高级查找算法。索引是在存储引擎中实现的,每种存储引擎的索引不一定完全相同。存储引擎可以定义每个表的最大索引数和最大索引长度。

优点:

提高了数据检索的效率,降低了数据库的IO成本。

通过创建唯一索引,可以保证数据库表中每一行和数据的唯一性。在实现数据的参考完整性方面,可以加速表和表之间的连接,对于依赖关系的子表和父表联合查询时,可以提高查询速度。

使用分组和排序子句时,可以减少查询中分组和排序的时间,降低了CPU的消耗。

缺点:

创建索引和维护索引要耗费时间,数据量的增加,其所耗费的时间也会增加。

索引需要占磁盘空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,存储在磁盘上。如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。

会降低更新表的速度,对表中数据进行增删改操作时,索引也要动态地维护,降低了数据的维护速度。

B+树索引:

不论是用户记录的数据页,还是存放目录项的数据页,都存放到B+树这个数据结构中。将数据页称为节点,实际用户记录存放在B+树的叶子节点上,其余用于存放目录项的节点为非叶子节点或者内节点。

B+树的深度越小,磁盘I/O次数越少。B+树索引分为聚簇索引(主键索引)和非聚簇索引(二级索引、辅助索引)。

根页面的位置不动:

当创建一个B+树索引时,都会创建一个根节点页面。最开始没有数据时,对应的B+树的根节点没有任何记录。当插入用户记录时,会存储到根节点当中。当根节点的空间用完时继续插入数据,此时根节点的所有记录复制到一个新分配的页,然后对新分配的页进行页分裂,得到另一个新页。这时插入的记录会根据简直的大小分配到页中,而根节点便存储目录项记录。InnoDB存储引擎需要用到这个索引时,会从固定的地方取出根节点的页号,来访问这个索引。

非叶子节点中目录项记录的唯一性:

索引列必须是唯一的。为了保证新插入的数据能找到对应的页。所以对于非聚簇索引的非叶子节点的目录项记录的内容实际上是由三个部分组成的:索引列的值,主键值,页号。主键值主要是为了保证目录项记录除了页号这个字段是唯一的。

一个页面最少存储2条记录:

如果存储一条记录,那么就成了单向链表。

B+树的特点:

B+树的查询效率更稳定,因为B+树只能访问到叶子节点才能找到对应的数据。B+树的查询效率更高,因为B+树深度更低,阶数更大,所以磁盘I/O的次数也会更少。查询范围上B+树的效率高,因为数据都出现在叶子节点中,叶子节点之间会有指针,数据又是递增的,索引范围查找可以通过指针连接查找。

聚簇索引:

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式,所有用户记录都存储在了叶子节点,也就是索引既数据,数据既索引。只能在搜索条件是主键时才能发挥作用。

特点:

使用记录的主键值的大小进行记录和页的排序:

页内的记录是按照主键的大小顺序排成一个单向链表。

存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表。

存放目录项记录的页分为不同的层次,在同一层次中的页也是根据目录项记录的主键大小顺序排成一个双向链表。

B+树的叶子节点存储的是完整的用户记录,也就是存储了所有列的值(包括隐藏列)。

聚簇索引不需要在MySQL语句中显示创建,InnoDB存储引擎会自动地创建聚簇索引。

优点:

数据访问更快,因为数据和索引保存在同一个B+树中,所以获取数据比非聚簇索引更快。

聚簇索引对于主键的排序查找和范围查找速度非常快。

因为数据都是紧密相连的,数据库不用从多个数据块中提取数据,节省了大量的IO操作。

缺点:

插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的,因为是按照主键的大小值进行排序。如果未按照主键的顺序插入,则会出现页分裂,严重影响性能。对于InnoDB表,一般都会定义一个自增的ID作为主键。

更新主键的代价很高,因为会导致被更新的行移动,因为按照主键的值的大小进行排序。对于InnoDB表,一般定义主键不可更新。

二级索引需要两次索引查找,先找到主键值,再根据主键值找到行数据(也就是回表)。

以上述可知:由于数据物理存储排序只能有一种,所以MySQL的表只能有一个聚簇索,一般情况就是主键。如果没有定义主键,会选择非空的唯一索引代替,但是都没有的话,那么会隐式定义一个主键作为聚簇索引。

主键列尽量选用有序的,避免出现行数据的移动和页分裂,充分利用聚簇索引的聚簇的特性。

非聚簇索引:

按照非主键列创建的B+树。进行对非主键列进行查询时,需要先找到其主键值,进行回表操作,才能找到完整的用户记录。

非聚簇索引的存在不影响数据在聚簇索引中的组织,所以一张表可以有多个非聚簇索引。非聚簇索引不会影响数据表的物理存储顺序。

聚簇索引与非聚簇索引的区别:

聚簇索引的叶子节点存储的是完整的数据记录,非聚簇索引叶子节点存储的是数据位置。

一个表只能有一个聚簇索引,因为只能有一种排序存储的方式,但可以有多个非聚簇索引,也就是多个索引目录提供数据检索。

聚簇索引的查询效率高,但是对数据的增删改操作效率会比非聚簇索引的效率低。

InnoDB存储引擎:

InnoDB的表中既存储数据又存储索引。在InnoDB中只包含一个聚簇索引,可以包含多个非聚簇索引。索引查询时只需要根据主键值对聚簇索引进行一次查找就能找到对应的数据记录,对于非主键列,需要在其非聚簇索引中找到其对应的主键值,然后通过回表操作找到主键值,取到相对应的完整数据记录。在InnoDB中是必须要求有主键。

MyISAM存储引擎:

MyISAM的表中数据和索引是分开存储的,将表中的记录按照插入的顺序单独存储在数据文件中,需要注意的是插入时没有按照主键值大小排序,所以不能使用二分查找。而索引信息另外存储到一个索引文件(仅保存数据记录的地址)。会单独为主键创建一个索引,只不过在所以的叶子节点中存储的不是完整的用户记录,而是主键值+数据记录地址的组合。

由此可知MyISAM存储引擎中通过B+树索引进行查询的话,只能通过键值找到其记录对应的数据记录地址之后进行回表操作,才能获取完整的数据记录。

InnoDB与MyISAM的区别:

InnoDB包含一个聚簇索引和非聚簇索引,而MyISAM的索引方式都是非聚簇索引。

InnoDB只需要根据主键值对聚簇索引进行一次查找就能找到其对应的数据记录,而在MyISAM中需要根据主键值找到其对应的数据记录地址之后进行一次回表操作。

InnoDB的数据文件本身就是索引文件,而MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。

InnoDB的非聚簇索引data域存储相应记录主键的值,而MyISAM索引记录是地址。

InnoDB的回表是根据主键值再聚簇索引中查询,但是相较于MyISAM的回表更慢,因为MyISAM中是根据地址偏移量直接到文件中取数据。

InnoDB要求必须要有主键,而MyISAM可以没有主键。

总结(B+树执行的流程):

首先从根节点开始,逐层向下遍历。通过非叶子节点存储的目录项的键值和查询的键值进行二分查找,选择合适的子节点,直到找到叶子节点。看叶子节点是否是完整的数据,如果不是完整数据,那么根据其对应的主键值,进行回表操作获取其完整的数据记录,如果是完整数据记录,那么直接返回。

http://www.xdnf.cn/news/17547.html

相关文章:

  • 嵌入式Linnux学习 -- 软件编程2
  • 【已解决】报错:WARNING: pip is configured with locations that require TLS/SSL
  • STM32——system文件夹
  • 【ros-humble】4.C++写法巡场海龟(服务通讯)
  • Spring Boot 中 @Transactional 解析
  • [Oracle] UNPIVOT 列转行
  • Linux kernel network stack, some good article
  • Day 37:早停策略和模型权重的保存
  • 《番外:Veda的备份,在某个未联网的旧服务器中苏醒……》
  • Mybatis学习之缓存(九)
  • 从零开始的云计算生活——第四十一天,勇攀高峰,Kubernetes模块之单Master集群部署
  • Seata
  • vue+django 大模型心理学智能诊断评测系统干预治疗辅助系统、智慧心理医疗、带知识图谱
  • EXISTS 替代 IN 的性能优化技巧
  • 前端灰度发布浅析
  • 【C++语法】输出的设置 iomanip 与 std::ios 中的流操纵符
  • 【stm32】EXTI外部中断
  • IoT/实现和分析 NB-IoT+DTLS+PSK 接入华为云物联网平台IoTDA过程,总结避坑攻略
  • 运维学习Day21——LAMP/LNMP 最佳实践
  • Python day 41
  • Linux 流编辑器 sed 详解
  • Linux-常用命令
  • Apache IoTDB 全场景部署:跨「端-边-云」的时序数据库 DB+AI 实战
  • 人工智能与农业:农业的革新
  • 超算中心的一台服务器上有多少个CPU,多少个核?
  • Spring JDBC
  • 构建轻量级Flask Web框架:从入门到实践
  • Spring Cloud Gateway 路由与过滤器实战:转发请求并添加自定义请求头(最新版本)
  • st.session_state 的存储机制
  • Docker中ES安装分词器