【MySQL进阶之路 | 高级篇】常见索引(聚簇索引, 二级索引)

1. 常见索引概念

索引按照物理实现方式,可以分为两种,聚簇索引和非聚簇索引.我们也把非聚簇索引称为二级索引或辅助索引.

(1). 聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式(所有的数据记录都存储在了叶子节点),也就是说所谓的索引即数据,数据即索引.MySQL8.0,在InnoDB存储引擎中索引和数据都存储在物理磁盘的.ibd文件中.

特点 : 

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

  • 页内记录是按照主键的大小顺序排成一个单向链表.
  • 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表.
  • 存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中记录主键值的大小顺序排成双向链表.

2. b+树的叶子节点存储的是完整的用户记录.即这个记录存储了所有列的值,包括InnoDB自己添加的隐藏列.

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

即一张新表,当插入一条记录时,底层就会自动构造b+树来创建索引.而不是等到添加很多记录后,才想起来使用INDEX语句才构造b+树创建索引.

如果表中有主键PRIMARY KEY,就会以该主键列创建索引,如果没有主键,则会选择一个非空唯一键来创建索引,如果即没有主键也没有唯一键,则会使用记录头信息中的隐藏列row_id来作为主键创建索引.

优点

  • 数据访问更快.因为聚簇索引将索引和数据都保存在同一个b+树中,因此聚簇索引比非聚簇索引查找速度更快.
  • 聚簇索引对于主键的排序查找和范围查找速度非常快.
  • 按照聚簇索引排列顺序,查询显示一定范围数据时,由于数据是相对紧密相连的,数据库不用从多个数据块中提取数据,节省大量的I/O操作.

缺点

  • 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能.因此,对于InnoDB表,我们一般都会定义一个自增的id列为主键.
  • 更新主键的代价很高. 因为将会导致被更新的行移动.因此对于InnoDB表我们一般定义主键为不可更新的.
  • 二级索引访问需要两次索引查找,第一次找到主键值,第二次通过主键值找到行数据.

限制

  • 对于MySQL数据库,目前只有InnoDB支持聚簇索引.而MyISAM不支持.
  • 由于数据物理存储排序方式只能有一种方式,所以每个MySQL的表只能有一个聚簇索引.一般情况下,即该表的主键.
  • 如果没有主键,会选择非空的唯一索引代替.如果也没有非空的唯一索引,InnoDB会隐式定义一个主键(row_id)作为聚簇索引.

(2). 二级索引

上面介绍的聚簇索引只能在搜索条件是主键值时才能发挥作用.因为b+树中的数据都是按照主键值的顺序来排序的.那么如果我们想根据别的列作为搜索条件该咋办呢.

我们可以多建几个b+树. 不同的b+树中的数据采用不同的排序规则.比方说我们用c2列来构建一个b+树.

78e7625e3b6c46a4bb7d3c8f18b1854f.png

该b+树与上述聚簇索引的b+树有几点不同.

  • 使用记录c2的列的大小进行记录和页的排序.
  • b+树的叶子节点存储的不是完整的用户记录.而是c2列+主键这两个列的值.通过该主键值再进行回表操作去聚簇索引的b+树中查询完整的记录.
  • 目标项记录不再是主键+页号,而是c2列+页号.

问 : 我们为什么需要回表.

如果把完整的用户记录放到叶子节点是可以不用回表的,但太占地方了.相当于每创建一个b+树都需要把所有的用户记录再都拷贝一遍,过于浪费存储空间.

因为这种按照非主键列建立的b+树需要一次回表的操作才可以定位到完整的用户记录.所以把这种b+树结构叫做二级索引.由于我们使用的是c2列的大小作为b+树的排序规则,所以我们称为这个b+树为c2列建立的索引.

与聚簇索引的区别.

  • 聚簇索引的叶子节点存储的是我们的数据记录,非聚簇索引的叶子节点存储的是数据位置.非聚簇索引不会影响数据表的物理存储结构.
  • 一个表只能有一个聚簇索引.因为只有一种依据主键的排序方式.但可以有很多个非聚簇索引.也就是多个索引提供数据检索.
  • 使用聚簇索引的时候,数据查询效率很高.但如果对数据进行插入删除更改等操作时,效率会比非聚簇索引的低.

3. 联合索引

我们也可以多个列的大小作为排序规则.也就是为多个列建立索引.比如我们想让b+树按照c2列和c3列的大小进行排序.这个包含两层含义.

  • 先把各个记录和页按照c2列排序
  • 当记录的c2列的值相同时,采用c3列进行排序.

5af2db1ff0ce411c9bfa25c88b88ccd1.png

以c2列c3列的大小为排序规则建立的b+树本质上也是二级索引.

2. InnoDB的b+树索引的注意事项

(1). 根页面位置万年不动

我们前面介绍b+树索引的时候,为了理解的方便,都是先把存储用户记录的叶子节点都画出来,然后接着画存储目录项记录的内节点.实际上,b+树的形成过程是这样的.

  • 每当为某个表创建一个b+树索引的时候,都会为这个索引创建一个根节点页面.最开始表中没有数据,每个+树索引对应的根节点中既没有用户记录,也没有目录项记录.
  • 随后向表中插入用户记录时,先将用户记录存储到这个根节点中.
  • 当根节点中的可用空间用完时继续插入,此时会将根节点中的所有记录复制到一个新分配的页,比如页a,然后对这个新页进行页分裂操作,得到新页页b.这时新插入的记录根据主键值的大小会被分配到页a或页b中.而根节点便升级为存储目录项的记录的页.

一个b+树索引的根节点子诞生开始,便不再移动.这样我们只要对某个表建立一个索引,那么它的根节点的页号便被记录到某个地方,然后凡是InnoDB存储引擎需要用到这个索引的时候,都会从固定的地方取出根节点的页号,从而访问该索引.

(2). 内节点中目录项记录的唯一性

我们知道b+树索引的内节点(非叶子节点)目录项记录的内容是索引列+页号.但这个搭配对二级索引来说有点不严谨.假设有个表的数据是这样的.

e3a44b13a2f541e6b30424df9a069609.png

如果二级索引中目录项记录的内容只是索引列+页号,那么为c2列建立索引后的b+树应该长这样.

d2122286865d4b36a9892c1dc14cf312.png

当我们想插入一行记录时,values(9,1,'c'),新插入的记录并不知道该放到页4还是页5.

如果我们把主键值也添加到二级索引内节点的目录项记录中,这样能保证b+树每一层节点中各条目录项记录除页号外是唯一的.所以我们为c2列建立二级索引后的示意图应该是这样的.

033fb9e836dc4afebd68883617806ba5.png

所以目录项记录中也必须存储主键值.而数据项记录中由于需要回表操作需要存储主键值这是毋庸置疑的.

(3). 一个页面最少存储两条记录

废话.

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

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

相关文章

js如何使得四舍五入的百分比之和为100%

在JavaScript中,如果你想要确保一组四舍五入后的百分比之和严格等于100%,那么你不能直接对每个百分比进行四舍五入,因为四舍五入会引入误差。但是,你可以采用一种策略,即先对所有的百分比进行常规的四舍五入&#xff0…

C# WPF入门学习主线篇(二十九)—— 绑定到对象和集合

C# WPF入门学习主线篇(二十九)—— 绑定到对象和集合 在WPF中,数据绑定是开发动态和交互性用户界面的核心技术。通过数据绑定,我们可以轻松地将UI控件与后台的数据源连接起来,实现数据的自动更新和显示。在本篇文章中&…

深度学习跨平台环境问题

在深度学习过程中,不可避免的是在win上跑不通的代码在ubuntu中就可以跑通,这里建议使用autodl。 首先在ubuntu上导出环境(如果你的环境是base的话使用base) conda env export --name base --no-builds > environment.yaml 这…

wordpress 导航主题 有批量从源码导入功能

下载地址:wordpress导航主题 可以批量导入

ardupilot开发 --- Jetson Orin Nano 后篇

我拼命加速,但贫穷始终快我一步 0~1920. visp-d455:基于IBVS的Pixhawk无人机视觉伺服20.1 基础关于连接、通讯、UDP forward服务:一些相关的、有用的例程Linux C程序的gdb断点调试搭建仿真解决【testPixhawkDroneTakeoff.cpp例程能解锁但起飞…

物联网LORA技术-SX1276/SX1277/SX1278-137MHz至1020MHz低功耗远距离收发器

概述: SX1276/SX1277/SX1278 收发器主要采用LORATM 远程调制解调器,用于超长距离扩频通信,抗干扰性强,能够最大限度降低电流消耗。借助升特的LoRaTM 专利调制技术,SX1276/SX1277/SX1278 采用低成本的晶体和物料即可获得…

SHELL脚本学习(十)初识 sed编辑器

一、sed 编辑器 sed 编辑器被称作流编辑器,根据命令来处理数据流中的数据。 这些数据要么从命令行输入,要么保存在命令文本文件中。 sed编辑器可以执行下列操作: 从输入中读取一行数据根据所提供的命令匹配数据按照命令修改数据流中的数据将…

WIFI6E中的MESH组网功能

什么是WIFI6E和MESH组网? WIFI 6E 是扩展到6GHz 频段的WIFI 6无线通信技术,而“WIFI 6E”中的“6”是指WIFI技术的“第6代”,“E”则是指使用新频段的标准的最新扩展。WIFI 6E通过增加6GHz频段,提供更高的带宽、更低的延迟和更大…

VMware虚拟机下载安装Windows Server 2016

「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等…

从新手小白到红酒大咖:解锁红酒品鉴的终极秘籍,升级之路全攻略

在五彩斑斓的饮品世界中,红酒以其深邃的色泽、丰富的口感和悠久的历史,吸引了无数人的目光。对于红酒的初学者来说,从小白到品鉴师的道路或许充满了未知与挑战,但只要掌握了正确的知识和方法,就能够轻松踏入这个美妙的…

用群辉NAS打造影视墙(Jellyfin篇)

目录 1、安装Jellyfin媒体服务器 2、配置 (1)语言 (2)管理员账户 (3)添加媒体库 (4)指定元数据语言 (5)远程访问设置 (6)修改文件夹权限 (7)刷新电影 (8)启用硬件加速 3、PC浏览器访问 4、手机客户端 5、智能TV客户端 6、解决演员不能显示中文的问…

Android SurfaceFlinger——注册监听调用流程(七)

这一篇我们介绍一下 IComposer 中的另一个比较重要的方法,通过注册监听 Hal 层实现监听驱动的关键动作。 一、注册监听 在前面文章 SurfaceFlinger 的 init() 方法中,我们注册了一个 Callback 到 Hal 层中。最终通过 HIDL 调用到 Hal 层。 1、SurfaceF…

Java从小白到入职 视频教程 下载 因为太大存百度云盘4.zip

Java从小白到入职 视频教程 下载 1---战前准备_00-课程介绍&个人简介.mp4 2---战前准备_00-02-学习方法.mp4 3---战前准备_00-03-你的角色.mp4 4---战前准备_00-04-学习工具.mp4 5---战前准备_00-05-技术岗位概述-Web前端.mp4 6---战前准备_00-06-技术岗位概述-Java语…

Jenkins+gitee流水线部署springboot项目

目录 前言 一、软件版本/仓库 二、准备工作 2.1 安装jdk 11 2.2 安装maven3.9.7 2.3 安装docker 2.4 docker部署jenkins容器 三、jenkins入门使用 3.1 新手入门 3.2 jenkins设置环境变量JDK、MAVEN、全局变量 3.2.1 jenkins页面 3.2.2 jenkins容器内部终端 3.2.3 全…

购物返利系统中的数据处理与优化策略

购物返利系统中的数据处理与优化策略 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 随着电商行业的不断发展,购物返利系统作为一种常见的营销手段…

python-赏月

[题目描述] 在某个星球上看到的月亮大小有一个规律,月亮为每30天一个周期,在这30天的周期里,月亮的大小分别为 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1。 虽然天气很冷,但这个星球上的某个居民今…

MyBatis 源码分析--SqlSessionFactory

前言: 前文我们简单的回顾了 MyBatis 的基本概念,有聊到核心组件,工作流程等,本篇我们开始深入剖析 MyBatis 的核心源码,欢迎大家持续关注。 Mybatis 知识传送门 初识 MyBatis 【MyBatis 核心概念】 MyBatis 源码解…

钒能新材料综合回收利用,钒溶液净化富集工艺之离子交换法

钒电池储能产业作为典型的绿色低碳优势产业,是新型储能领域重要发展方向。钒电池储能具备大规模、长周期等优势,是储能领域的重要组成部分,将成为拓展电能利用、应对可再生能源随机波动、支撑可再生能源高占比电力系统的最佳技术途径之一。 …

力扣1019.链表中的下一个更大节点

力扣1019.链表中的下一个更大节点 从左到右 每个数确定下一个更大节点后 弹出栈中存下标 即res.size() class Solution {public:vector<int> nextLargerNodes(ListNode* head) {vector<int> res;stack<int> st;for(auto ihead;i;ii->next){while(!st.e…

openEuler 24.03 LTS - 华为欧拉开源版(华为 RHEL 兼容发行版)

openEuler 24.03 LTS - 华为欧拉开源版&#xff08;华为 RHEL 兼容发行版&#xff09; 华为红帽企业 Linux 兼容发行版 请访问原文链接&#xff1a;https://sysin.org/blog/openeuler/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sy…