MYSQL06高级_为什么使用索引、优缺点、索引的设计、方案、聚簇索引、联合索引

news2024/10/7 12:17:34

文章目录

  • ①. 为什么使用索引
  • ②. 索引及其优缺点
  • ③. InnoDb - 索引的设计
  • ④. InnoDb中的索引方案
  • ⑤. 索引 - 聚簇索引
  • ⑥. 索引 - 二级索引

①. 为什么使用索引

  • ①. 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比去图书馆找书,或者新华字典里找字,相当于一个目录,可以帮助我们快速的查找到数据所在的位置

  • ②. 在MySQL中也是同样的道理,进行数据查找时,首先看查询条件是否命中索引,符合则通过索引查找相关数据,如果不符合则需要全表扫描,即一条一条的查找记录,直到找到与条件符合的记录
    在这里插入图片描述

  • ③. 假如给数据使用二叉树这样的数据结构进行存储,如下图所示
    建立索引目的是为了减少磁盘I/O次数,加快查询效率
    在这里插入图片描述

②. 索引及其优缺点

  • ①. MySQL官方对索引的定义为:索引是帮助MySQL高效获取数据的数据结构

  • ②. 本质:索引是数据结构,可以理解为“排好序的快速查找数据结构

  • ③. 索引是在存储引擎中实现的,因此每种存储引擎的索引不一定完全相同,并且每种存储引擎不一定支持所有索引类型

  • ④. 优点

  1. 提高数据检索效率,降低数据库的IO成本
  2. 通过创建唯一索引,可以保证数据库表中每一行数据的唯一性
  3. 在实现数据的参考完整性方面,可加速表和表之间的连接。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询效率
  4. 在使用分组和排序子句进行数据查询时,可以显著减少查询中分组和排序的时间,降低了CPU的消耗
  • ⑤. 缺点
  1. 创建索引和维护索引要消耗时间,并且随着数据量的增加,所耗费的时间也会增加
  2. 索引需要占用磁盘空间,除了数据表占数据空间外,每一个索引还要占一定的物理空间,存储在磁盘上,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸
  3. 虽然索引大大提高了查询速度,同时却会降低更新表的速度。当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度

③. InnoDb - 索引的设计

  • ①. 首先,建一个表:
    这个新建的index_demo表有2个INT类型的列,1个CHAR类型的列,而且规定了c1位逐渐,这个表使用Compact行格式来实际存储记录,行格式之后会学习到。以下是简化了行格式的示意图:
    在这里插入图片描述
CREATE TABLE index_demo(
	c1 INT,
	c2 INT,
	c3 CHAR(1),
	PRIMARY KEY (c1)
) ROW_FORMAT = Compact;
  • ②. 我们只在示意图中展示记录这几个部分
  1. record_type:记录头信息的一项属性,表示记录的类型,0表示普通记录、2表示最小记录、3表示最大记录、1是目录项
  2. next_record:记录头信息的一项属性,表示下一条地址相对于本条记录的地址偏移量,我们用箭头来表明下一条记录是谁。可以理解为链表
  3. 各个列的值:这里只记录在index_demo表中的三个列,分别是c1,c2,c3
  4. 其他信息:除了上述3种信息以外的所有信息,包括其他隐藏列的值以及记录的额外信息

在这里插入图片描述在这里插入图片描述

  • ③. 下一个数据页中用户记录的主键值必须大于上一个页中用户记录的主键值
  1. 假设:每一个数据页最多能存放三条记录,实际上一个数据页非常大,可以存放好多记录。向表中插入3条记录,填充数据页
INSERT INTO index_demo VALUES(1,4,'u'),(3,9,'d'),(5,3,'y');
  1. 那么这些记录已经按照主键值的大小串联成一个单向链表了
    在这里插入图片描述3. 那这时候我们插入一条主键为4的记录,这个数据页已经显示不下了,只能新建一个数据页,而且因为4 < 5,所以这条记录应该保存在页10中,把主键为5的记录移动到下一个页中,这个过程叫页分裂
    在这里插入图片描述
  • ④. 给所有的页建立一个目录项 - 由于数据页的编号可能是不连续的,所以插入了多条记录后,可能会出现以下的情况
    在这里插入图片描述
  • ⑤. 因为这些数据页在物理存储上是不连续的,所以如果想从这么多页中根据主键值快速定位某些记录所在的位置,我们需要给他们做一个目录,每一个页对应一个目录项,每个目录项包括下边两个部分:
  1. 比如:查找主键值为20的记录,具体查找过程分两步:
  2. 先从目录项中根据二分法快速确定出主键值为20的记录在目录项3中因为12 < 20 <209),它对应的页 - 是页9
  3. 再根据前边说的在页中查找记录的方式去页9中定位具体的记录
    在这里插入图片描述
  • ⑥. 针对数据页做的简易目录就搞定了。这个目录有一个别名,称为索引

④. InnoDb中的索引方案

  • ①. 迭代1次:目录项纪录的页 - 我们把前边使用到的目录项放到数据页中的样子就是这样
    在这里插入图片描述
  • ②. 从图中可以看出来,我们新分配了一个编号为30的页来专门存储目录项记录。这里再次强调目录项记录和普通的用户记录的不同点:
  1. 目录项记录的record_type值是1,而普通用户记录的record_type值是0
  2. 目录项记录只有主键值和页的编号两个列,而普通的用户记录的列是用户自己定义的,可能包含很多列 ,另外还有InnoDB自己添加的隐藏列
  3. 了解:记录头信息里还有一个叫min_rec_mask的属性,只有在存储目录项记录的页中的主键值最小的目录项记录的min_rec_mask值为1 ,其他别的记录的min_rec_mask值都是0
  • ③. 相同点:两者用的是一样的数据页,都会为主键值生成 Page Directory 页目录,从而在按照主键值进行查找时可以使用二分法来加快查询速度
  1. 现在以查找主键为 20 的记录为例,根据某个主键值去查找记录的步骤就可以大致拆分成下边两步:
  2. 先到存储目录项记录 的页,也就是页30中通过 二分法 快速定位到对应目录项,因为12 < 20 <209 ,所以定位到对应的记录所在的页就是页9
  3. 再到存储用户记录的页9中根据二分法 快速定位到主键值为20的用户记录
  • ④. 迭代2次:多个目录项纪录的页
    在这里插入图片描述在这里插入图片描述
  • ⑤. 迭代3次:目录项记录页的目录页
    如图,我们生成了一个存储更高级目录项的页33 ,这个页中的两条记录分别代表页30和页32,如果用户记录的主键值在 [1, 320) 之间,则到页30中查找更详细的目录项记录,如果主键值不小于320的话,就到页32中查找更详细的目录项记录
    在这里插入图片描述
  • ⑥. 我们可以用下边这个图来描述它 - 这个数据结构,它的名称是B+树

在这里插入图片描述

  • ⑦. 一个B+树的节点其实可以分成好多层,规定最下边的那层,也就是存放我们用户记录的那层为第0层,之后依次往上加。之前我们做了一个非常极端的假设:存放用户记录的页 最多存放3条记录 ,存放目录项记录的页最多存放4条记录 。其实真实环境中一个页存放的记录数量是非常大的,假设所有存放用户记录的叶子节点代表的数据页可以存放100条用户记录 ,所有存放目录项记录的内节点代表的数据页可以存放1000条目录项记录 ,那么
  1. 如果B+树只有1层,也就是只有1个用于存放用户记录的节点,最多能存放100条记录
  2. 如果B+树有2层,最多能存放1000×100=10,0000条记录
  3. 如果B+树有3层,最多能存放1000×1000×100=1,0000,0000条记录
  4. 如果B+树有4层,最多能存放 1000×1000×1000×100=1000,0000,0000条记录。相当多的记录
  5. 你的表里能存放100000000000条记录吗?所以一般情况下,我们用到的B+树都不会超过4层 ,那我们通过主键值去查找某条记录最多只需要做4个页面内的查找查找3个目录项页和一个用户记录页,又因为在每个页面内有所谓的Page Directory页目录,所以在页面内也可以通过二分法实现快速定位记录

⑤. 索引 - 聚簇索引

  • ①. 使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
  1. 页内的记录是按照主键的大小顺序排成一个单向链表
  2. 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表
  3. 存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表
  • ②. B+树的叶子节点存储的是完整的用户记录
    完整的用户记录,就是指这个记录中存储了所有列的值包括隐藏列

  • ③. 们把具有这两种特性的B+树称为聚簇索引,所有完整的用户记录都存放在这个聚簇索引的叶子节点处。这种聚簇索引并不需要我们在MySQL语句中显式的使用INDEX语句去创建,InnoDB存储引擎会自动的为我们创建聚簇索引

  • ④. 聚簇索引优点

  1. 数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
  2. 聚簇索引对于主键的排序查找和范围查找速度非常快
  3. 按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以节省了大量的io操作
  • ⑤. 聚簇索引缺点
  1. 插入速度严重依赖插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能,因此对于InnoDB表,我们一般都会定义一个自增的ID列为主键
  2. 更新主键的代价很高,因为将会导致被更新的行移动。因此对于InnoDB表,我们一般定义主键为不可更新
  • ⑥. 限制
  1. 对于MySQL数据库,目前只有InnoDB数据引擎支持聚簇索引,而MyISAM并不支持聚簇索引
  2. 由于数据物理存储排序方式只能由有一种,所以每个MySQL的表只能有一个聚簇索引。一般情况下就是该表的主键
  3. 如果没有定义主键,InnoDB会选择非空的唯一索引代替。如果没有这样的索引,InnoDB会隐式的定义一个主键来作为聚簇索引
  4. 为了充分利用聚簇索引的聚簇的特性,索引InnoDB表的主键列尽量选择有序的顺序id,而不建议用无序的id,比如UUID、MD5、HASH、字符串列作为主键无法保证数据的顺序增长
  • ⑦. 聚簇索引并不是一种单独的索引类型,而是一种数据存储方式(所有的记录都存储在了叶子节点),也就是所谓的索引即数据,数据即索引

⑥. 索引 - 二级索引

  • ①. 二级索引也被称为辅助索引、非聚簇索引,上面介绍的聚簇索引只能在搜索条件是主键时才能发挥作用,因为B+树的数据都是按照主键进行排序的
    在实际开发过程中,我们经常使用别的列作为搜索条件,如果使用该列为搜索条件的频率非常高时,我们就可以考虑使用此列创建一个二级索引,依次来提升搜索的速度
    在这里插入图片描述
  • ②. 使用记录c2列的大小进行记录和页的排序,这包括三个方面的含义
  1. 页内的记录是按照c2列的大小顺序排成一个单向链表
  2. 各个存放用户记录的页也是根据页中用户记录的c2列的大小顺序排成一个双向链表
  3. 存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的c2列的大小顺序排成一个双向链表
  • ③. B+树的叶子节点存储的并不是完整的用户记录,而只是c2列+主键这两个列的值

  • ④. 目录项记录中不再是主键+页号的搭配,而是c2列+页号的

  • ⑤. 通过二级索引搜索,需要先从二级索引的B+树找到符合条件的主键id,然后再去聚簇索引的B+树进行搜索。这里就会有同学想问了,为什么不在二级索引的B+树中存储完整的用户记录呢?
    如果把完整的用户记录放到叶子节点是可以不用回表,但是太占用地方了,相当于每创建一个索引,就将用户记录都拷贝一份,非常浪费存储空间

  • ⑥. 聚簇索引与非聚簇索引的原理不同,在使用上也有一些区别

  1. 聚簇索引的叶子节点存储的就是我们的数据记录,非聚簇索引的叶子节点存储的是数据位置。非聚簇索引不会影响表的物理存储数据
  2. 一个表只能由一个聚簇索引,因为只能有一种排序存储方式,但可以有多个非聚簇索引
  3. 使用聚簇索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚簇索引低。这是因为修改非聚簇索引,只需要操作当前的B+树,而如果修改聚簇索引,不仅要操作当前B+树,所有非聚簇索引的叶子节点的id都需要修改
  • ⑦. 联合索引也是二级索引的一种,如果我们使用了多个列创建索引,例如先按照c2排序,c2相同按照c3排序,那么这就是一个联合索引。
    联合索引相较于二级索引,在每一个节点上存储的数据更多了,这里就画一个草图,不再赘述了

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/842206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react搭建在线编辑html的站点——引入grapes实现在线拖拉拽编辑html

文章目录 ⭐前言⭐搭建react ts项目⭐引入grapes 插件⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于react搭建在线编辑html的站点。 react 发展历史 React是由Facebook开发的一种JavaScript库&#xff0c;用于构建用户界面。React最初发布于2013年&…

MySQL两种存储引擎及索引对比

MySQL两种存储引擎及索引对比 前言存储引擎主要区别相关命令存储引擎1: MyISAM存储引擎2: InnoDB其他存储引擎: 索引聚集&#xff08;聚簇&#xff09;索引二级索引 常见面试题为什么 DBA 都建议表中一定要有主键&#xff0c;而且推荐使用整型自增&#xff1f;为什么要有主键&a…

ElasticSearch7.6入门学习笔记

在学习ElasticSearch之前&#xff0c;先简单了解一下Lucene&#xff1a; Doug Cutting开发 是apache软件基金会4 jakarta项目组的一个子项目 是一个开放源代码的全文检索引擎工具包不是一个完整的全文检索引擎&#xff0c;而是一个全文检索引擎的架构&#xff0c;提供了完整的…

Yolov8-pose关键点检测:模型轻量化设计 | 引入Ghostnet、G_ghost、Ghostnetv2、repghost,进行性能对比

💡💡💡本文解决什么问题:Yolov8-pose关键点评估不同轻量级网络的性能,引入Ghostnet、G_ghost、Ghostnetv2、repghost等网络进行可行性分析 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_63774211/category_12398833.html ✨✨✨手把手教你从数据标记到生…

计算成像最新论文速览 | TPAMI 2023,使用光谱内容隔离非视距成像中的信号

计算成像最新论文速览 | TPAMI 2023,使用光谱内容隔离非视距成像中的信号 注1:本文系“计算成像最新论文速览”系列之一,致力于简洁清晰地介绍、解读计算成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‑Scien…

Python程序设计基础:函数(一)

文章目录 一、函数的基本概念二、函数的定义和使用1、函数的定义与调用2、函数的参数3、返回多个值 一、函数的基本概念 在使用Python实现某些复杂的功能的时候&#xff0c;容易遇到一些重复率较高的代码&#xff0c;为了代码能够重复使用并提升代码的整洁度&#xff0c;函数这…

【Spring Boot】Spring Boot 集成 RocketMQ 实现简单的消息发送和消费

文章目录 前言基本概念消息和主题相关发送普通消息 发送顺序消息RocketMQTemplate的API介绍参考资料&#xff1a; 前言 本文主要有以下内容&#xff1a; 简单消息的发送顺序消息的发送RocketMQTemplate的API介绍 环境搭建&#xff1a; RocketMQ的安装教程&#xff1a;在官网…

JNI之Java实现蓝牙交互

蓝牙概述 蓝牙&#xff0c;是一种支持设备短距离通信&#xff08;一般10m内&#xff09;的无线电技术&#xff0c;能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间&#xff0c;通过蓝牙设备之间的无线通信实现数据传输&#xff0c;实现数据传输&#xf…

golang代码热加载,热更新库air库实践

windows下先生成air.exe文件&#xff0c;然后移动到golang的执行目录&#xff1a; 2.简介 air是一款基于golang开发的实时热加载工具&#xff0c;通过使用该工具&#xff0c;使得开发人员能专注于coding&#xff0c;而不会被编译过程打断。 项目地址: https://github.com/cos…

【工作中问题解决实践 九】Spring中事务传播的问题排查

最近在工作中遇到了两个关于事务操作的问题&#xff0c;顺便就着这两个问题又回顾了一遍Spring的事务相关的操作&#xff0c;想着一次性把这个问题研究明白了&#xff0c;后续使用事务的时候也能踏实点&#xff0c;让事务发挥真实的作用 什么是事务&#xff1f;什么是事务管理…

【探索Linux】—— 强大的命令行工具 P.2(Linux下基本指令)

前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0c;并且讲了有关C的一些知识&#xff0c;也相信大家都掌握的不错&#xff0c;今天博主将会新开一个Linux专题&#xff0c;带领大家继续学习有关Linux的内容。今天第一篇文章博主首先带领大家了解一下…

客服型电话呼叫中心系统,助力企业提升客户服务质量

客服型电话呼叫中心系统是企业客户服务的重要工具之一&#xff0c;它通过电话和网络等方式&#xff0c;为客户提供快速、便捷、高效的服务。客服型电话呼叫中心系统具备自动接听来电、自动路由、管理知识库、录音和监控、生成报表分析等多种功能&#xff0c;有利于企业提高客户…

IP提取器对比器

需求&#xff1a; 一个html 页面 &#xff0c;有两个输入框 第一个输入框输入文本中包含多个ip&#xff0c;输入的ip是不规则的&#xff0c;需要使用正则表达式提取出 输入文本的ip地址 &#xff0c; 然后在第二个输入框中输入内容&#xff0c;并提取出内容的ip &#xff0c;如…

实时渲染与传统渲染有啥区别?实时渲染器有哪些

您是否曾经玩过 3D 视频游戏&#xff0c;或观看过让您感觉身处真实的建筑环境&#xff1f;如果是&#xff0c;那么您已经体验过实时渲染。和传统的渲染有什么不同吗&#xff1f;在本文中了解有关实时渲染的所有信息。 什么是实时渲染&#xff1f; 为了更容易理解什么是实时渲…

jupyter文档转换成markdown

背景 上一篇文章**《如何优雅地用python生成模拟数据》**我就使用jupyter写的&#xff0c;这个真的是万能的&#xff0c;可以插入markdown格式的内容&#xff0c;也可写代码&#xff0c;关键是像ipython一样&#xff0c;可以分步执行。 我可以这样自由的写我的博客内容&#x…

Docker入门——保姆级

Docker概述 ​ —— Notes from WAX through KuangShen 准确来说&#xff0c;这是一篇学习笔记&#xff01;&#xff01;&#xff01; Docker为什么出现 一款产品&#xff1a;开发—上线 两套环境&#xff01;应用环境如何铜鼓&#xff1f; 开发 – 运维。避免“在我的电脑…

【Groups】50 Matplotlib Visualizations, Python实现,源码可复现

详情请参考博客: Top 50 matplotlib Visualizations 因编译更新问题&#xff0c;本文将稍作更改&#xff0c;以便能够顺利运行。 1 Dendrogram 树状图根据给定的距离度量将相似的点组合在一起&#xff0c;并根据点的相似性将它们组织成树状的链接。 新建文件Dendrogram.py: …

怎样在pdf上直接修改?看看这几种修改方法

怎样在pdf上直接修改&#xff1f;PDF是一种非常流行的文件格式&#xff0c;它在保持文档格式不变的同时也可以压缩文件大小&#xff0c;便于分享。尽管 PDF 文件很便捷&#xff0c;但是在 PDF 上进行修改却是一件比较困难的事情。幸运的是&#xff0c;有很多工具可以帮助你在 P…

AUTOSAR笔记2:AP主要模块

1 CM CM&#xff08;Communication Management&#xff09;组件提供独立于网络和协议的应用间通信服 务&#xff0c;支持如下功能&#xff1a; 服务发现&#xff0c;包括服务注册、服务查找等&#xff1b;应用间通信&#xff0c;支持单向数据收发&#xff08;Event&#xff0…

STM32入门——定时器

内容为江科大STM32标准库学习记录 TIM简介 TIM&#xff08;Timer&#xff09;定时器定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断16位计数器、预分频器、自动重装寄存器的时基单元&#xff0c;在72MHz计数时钟下可以实现最大59.65s的定时&…