MySql Innodb 索引有哪些与详解

news2024/10/7 6:43:12

概述

对于MYSQL的INNODB存储引擎的索引,大家是不陌生的,都能想到是 B+树结构,可以加速SQL查询。但对于B+树索引,它到底“长”得什么样子,它具体如何由一个个字节构成的,这些的基础知识鲜有人深究。本篇文章从MYSQL行记录开始说起,层层递进,包括数据页,B+树聚簇索引,B+树二级索引,最后在文章末尾给出MYSQL索引的建议。

表空间

首先,我们来了解一下 MySQL 的表空间。在 MySQL 中,所有的数据都被存储在一个空间内,称之为表空间,表空间内部又可以分为段(segment)、区(extent)、页(page)、行(row),其逻辑结构如下图:

段(segment)

表空间是由不同的段组成的,常见的段有:数据段,索引段,回滚段等等,在 MySQL 中,数据是按照 B+ 树来存储,因此数据即索引,因此数据段即为 B+ 树的叶子节点,索引段为 B+ 树的非叶子节点,回滚段用于存储undo日志,用于事务失败后数据回滚以及在事务未提交之前通过undo日志获取之前版本的数据,在 InnoDB 1.1 版本之前,一个 InnoDB 只支持一个回滚段,支持 1023 个并发修改事务同时进行,在 InnoDB 1.2 版本,将回滚段数量提高到了 128 个,也就是说可以同时进行128 * 1023个并发修改事务。

区(extent)

区是由连续页组成的空间,每个区的固定大小为 1MB,为保证区中页的连续性,InnoDB 会一次从磁盘中申请 4 ~ 5 个区,在默认不压缩的情况下,一个区可以容纳 64 个连续的页。但是在开始新建表的时候,空表的默认大小为 96KB,是由于为了高效的利用磁盘空间,在开始插入数据时表会先利用 32 个页大小的碎片页来存储数据,当这些碎片使用完后,表大小才会按照 MB 倍数来增加。

页(page)

页是 InnoDB 存储引擎的最小管理单位,每页大小默认是 16KB,从 InnoDB 1.2.x 版本开始,可以利用innodb_page_size来改变页大小,但是改变只能在初始化 InnoDB 实例前进行修改,之后便无法进行修改,除非mysqldump导出创建新库,常见的页类型有:数据页、undo页、系统页、事务数据页、插入缓冲位图页、插入缓冲空闲列表页、未压缩的二进制大对象页以及压缩的二进制大对象页等。

行(row)

行对应的是表中的行记录,每页存储最多的行记录也是有硬性规定的最多16KB/2-200,即 7992 行,其中 16KB 是页大小。

Clustered Index 聚簇索引

MySQL InnoDB 引擎具有强制聚簇索引,通常使用主键。也就是主键就是Clustered Index,如果没有主键按以下规则生成。

Clustered Index 条件优化级:
  1. 表有明确的PRIMARY KEY:使用PRIMARY KEY

  2. 无PRIMARY KEY:InnoDB 默认使用第一个 UNIQUE INDEX,且索引列需要全部定义为非空列(NOT NULL)作为Clustered Index

  3. 如无PRIMARY KEY,也没有合适的UNIQUE INDEX,InnoDB将会在包含行ROW ID的合成列上生成一个名为GEN_CLUST_INDEX的隐藏Clustered Index

ROW ID:ROW ID是6 byte字段,由InnoDB分配,用于行排序。插入新行而单调增加,在物理上插入按ROW ID顺序排列

注:UNIQUE INDEX 包含的列需要全部定义为NOT NULL非空,才会被当做Clustered Index

MyISAM 存储引擎不支持聚簇索引并且一直使用堆表

2. 聚簇索引如何加速查询

通过聚簇索引访问行很快,因为索引搜索直接指向包含行数据的页面。如果表很大,与使用与索引记录不同的页来存储行数据的存储组织相比,聚簇索引架构通常可以节省磁盘 I/O 操作。

3. Clustered Index 示例及查询:

INNODB_INDEXES 表type字段说明:

  • 0 = 非唯一索引的二级索引 :nonunique secondary index;

  • 1 = 自动生成的聚簇索引:automatically generated clustered index (GEN_CLUST_INDEX);

  • 2 = 唯一索引(非聚簇索引): unique nonclustered index;

  • 3 = 聚簇索引 clustered index;

  • 32 = 全文索引 full-text index

不同MySQL版本表名不同,使用命令查询:SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_%';

自动生成名为GEN_CLUST_INDEX的Clustered Index示例:

-- 创建无主键、无唯一索引 
CREATE TABLE `clustered_index_demo` (
  `id` int DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 查询表索引 
-- 如5.7以下版本表名不同,使用命令查询:SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_SYS%';
SELECT 
  t2.INDEX_ID ,
  t2.`NAME` , 
  t2.TABLE_ID , 
  t2.`TYPE` , 
  t2.N_FIELDS , 
  t2.PAGE_NO , 
  t2.`SPACE` , 
  t2.MERGE_THRESHOLD
FROM information_schema.INNODB_TABLES t1 
INNER JOIN information_schema.INNODB_INDEXES t2 ON t1.TABLE_ID = t2.TABLE_ID
WHERE t1.`NAME` = 'wiki/clustered_index_demo';

-- 查询结果

| INDEX_ID | NAME            | TABLE_ID | TYPE | N_FIELDS | PAGE_NO | SPACE | MERGE_THRESHOLD |
|----------|-----------------|----------|------|----------|---------|-------|-----------------|
|     3616 | GEN_CLUST_INDEX |     3276 |    1 |        5 |       4 |  2113 |  
增加包含NOT NULL列的唯一索引示例:

Tips : 修改表结构,InnoDB将删除原自动生成的GEN_CLUST_INDEX索引

-- 增加两列
ALTER TABLE `wiki`.`clustered_index_demo`
ADD COLUMN `username` varchar(32) NOT NULL,
ADD COLUMN `name` varchar(64) NOT NULL;
-- 增加唯一索引 
ALTER TABLE `wiki`.`clustered_index_demo`
ADD UNIQUE INDEX `IDX_UNIQUE` (`username`,`name`) USING BTREE;

| INDEX_ID | NAME       | TABLE_ID | TYPE | N_FIELDS | PAGE_NO | SPACE | MERGE_THRESHOLD |
|----------|------------|----------|------|----------|---------|-------|-----------------|
|     3620 | IDX_UNIQUE |     3278 |    3 |        5 |       4 |  2115 |              50 |
唯一索引包含NULL列
-- 将唯一索引,其中一列改为NULL, Clustered Index将被删除,重新生成GEN_CLUST_INDEX
ALTER TABLE `wiki`.`clustered_index_demo`
CHANGE `username` `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
CHANGE `name` `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL;

| INDEX_ID | NAME            | TABLE_ID | TYPE | N_FIELDS | PAGE_NO | SPACE | MERGE_THRESHOLD |
|----------|-----------------|----------|------|----------|---------|-------|-----------------|
|     3625 | GEN_CLUST_INDEX |     3281 |    1 |        6 |       4 |  2118 |              50 |
|     3626 | IDX_UNIQUE      |     3281 |    2 |        3 |       5 |  2118 |      

查询所有自动生成的Clustered Index

SELECT
	i.TABLE_ID,
	t.NAME
FROM
	information_schema.INNODB_INDEXES i
	JOIN information_schema.INNODB_TABLES t ON (i.TABLE_ID = t.TABLE_ID)
WHERE
	i.NAME = 'GEN_CLUST_INDEX';

| TABLE_ID | NAME                      |
|----------|---------------------------|
|     3281 | wiki/clustered_index_demo |

 辅助索引

除了聚簇索引之外的索引都可以称之为辅助索引,与聚簇索引的区别在于辅助索引的叶子节点中存放的是主键的键值。一张表可以存在多个辅助索引,但是只能有一个聚簇索引,通过辅助索引来查找对应的航记录的话,需要进行两步,第一步通过辅助索引来确定对应的主键,第二步通过相应的主键值在聚簇索引中查询到对应的行记录,也就是进行两次 B+ 树搜索。相反,通过辅助索引来查询主键的话,遍历一次辅助索引就可以确定主键了,也就是所谓的索引覆盖,不用回表。

创建辅助索引,可以创建单列的索引,也就是用一个字段来创建索引,也可以用多个字段来创建副主索引称为联合索引,创建联合索引后,B+ 树的节点存储的键值数量不是 一个,而是多个,如下图:

  • 联合索引的 B+ 树和单键辅助索引的 B+ 树是一样的,键值都是排序的,通过叶子节点可以逻辑顺序的读出所有的数据,比如上图所存储的数据时,按照(a,b)这种形式(1,1),(1,2),(2,1),(2,4),(3,1),(3,2)进行存放,这样有个好处,那就是存放数据时排序了,当进行order by对某个字段进行排序时,可以减少复杂度,加速进行查询;

  • 当用select * from table where a=? and ?可以使用索引(a,b)来加速查询,但是在查询时有一个原则,SQL 的where条件的顺序必须和二级索引一致,而且还遵循索引最左原则,select * from table where b=?则无法利用(a,b)索引来加速查询。

  • 辅助索引还有一个概念便是索引覆盖,索引覆盖的一个好处便是辅助索引不包含行记录,因此其大小远远小于聚簇索引,利用辅助索引进行查询可以减少大量的 IO 操作。

索引的优缺点及建议

 

优点:

  1. 对于等值查询,可快速定位到对于的行记录。

  2. 对于范围查询,可辅助缩小扫描区间。

  3. 当ORDER BY的列名 与 索引的列名完全一致时,可加快排序的顺序。

  4. 当GROUP BY的列名 与 索引的列名完全一致时,可加快分组。

  5. 当二级索引列中 包含了 SELECT 关键字后面写明的所有列,则在查询完成二级索引之后无需进行回表操作,直接返回即可。这种情况,称为【覆盖索引】。

缺点:

建立索引占用磁盘空间。

对表中的数据进行 增加,删除,修改 操作时,都需要修改各个索引树,特别是如果新增的行记录的主键顺序不是递增的,就会产生页分裂,页回收等操作,有较大的时间成本。

当二级索引列的值 的 不重复值的个数较少时,通过二级索引查询找到的数据量就会比较多,相应的就会产生过多的回表操作。

在执行查询语句的时候,首先要生成一个执行计划。通常情况下,一个SQL在执行过程中最多使用一个二级索引,在生成执行计划时需要计算使用不同索引执行查询时所需的成本,最后选择成本最低的那个索引执行查询。因此,如果建立太多的索引,就会导致成本分析过程耗时太多,从而影响查询语句的性能。

建议:

  1. 只为用于搜索,排序,分组的列创建索引。

  2. 索引的列需要有辨识性,尽可能地区分出不同的记录。

  3. 索引列的类型尽量小。因为数据类型越小,索引占用的存储空间就越少,在一个数据页内就可以存放更多的记录,磁盘I/O带来的性能损耗也就越小。

  4. 如果需要对很长的字段进行快速查询,可考虑为列前缀建立索引。【alter table table_M add index idx_key1(column_n(10)) -->  将table_M表的 idx_key1列的前10个字符创建索引】

  5. 覆盖索引,当二级索引列中包含了SELECT关键字后面写明的所有列,则在查询完成二级索引之后无需进行回表操作,直接返回即可。因此,编写【select *】的时候,要想想是否必要

  6. 在查询语句中,索引列不要参与条件值计算,也是把条件值计算完成之后,再和索引列对比。【否则MYSQL会认为搜索条件不能形成合适的扫描区间来减少扫描的记录数量】

 

 

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

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

相关文章

Python入门 2024/7/3

目录 for循环的基础语法 遍历字符串 练习:数一数有几个a range语句 三个语法 语法1 语法2 语法3 练习:有几个偶数 变量作用域 for循环的嵌套使用 打印九九乘法表 发工资案例 continue和break语句 函数的基础定义语法 函数声明 函数调用 …

数字化时代的新型共赢商业模式

在数字化时代的洪流中,一种名为“双轨订单协同增效模式”的新型商业架构正悄然兴起,它以别出心裁的理念和运作机制,在市场中开辟出了一片新天地。 一、模式概览 “双轨订单协同增效模式”根植于用户间的协同合作与订单流转优化。用户通过加入…

Ansys Maxwell 2024 R2更新介绍

Ansys Maxwell 2024 R2更新概览 具体更新介绍 01 Continuum Air [Beta] 02 New Power Electronics Solver 03 Combination of DC & AC Fields 04 More Features: More Capabilities…

视图库对接系列(GA-T 1400)四、视图库对接系列(本级)注册

视图库对接系列(本级)注册 在之前的步骤中,我们已经把项目大体的架构已经写出来了。那我们就来实现注册接口。 GA-T 1400中的步骤如下: 这里的话,我们实现的简单点, 我们不进去鉴权,也就是设备或平台找我们注册的话&…

在SpringBoot 3.0环境下创建一个SpringBoot 项目

一、环境配置 1.专业版的IDEA 版本号:尽量选择不要太老,不要太早 这里以2023.3.1为例。 官网:Download IntelliJ IDEA – The Leading Java and Kotlin IDE (jetbrains.com) 破解版:网上找资料哦!!&#…

【Python】基于动态规划和K聚类的彩色图片压缩算法

引言 当想要压缩一张彩色图像时,彩色图像通常由数百万个颜色值组成,每个颜色值都由红、绿、蓝三个分量组成。因此,如果我们直接对图像的每个像素进行编码,会导致非常大的数据量。为了减少数据量,我们可以尝试减少颜色…

thinkphp6/8 验证码

html和后台验证代码按官方来操作 ThinkPHP官方手册 注意: 如果验证一直失败,看看Session是否开启, 打印dump(session_status());结果2为正确的, PHP_SESSION_DISABLED: Session功能被禁用(返回值为0)。…

awtk-web 增加模拟器外壳

界面效果 方法 将 data/simulator.html 拷贝到 app目录下,覆盖index.html将 data/simulator_bg.png 拷贝到 app目录下 动态效果

互联网盲盒小程序的市场发展前景如何?

近几年来,盲盒成为了大众热衷的消费市场。盲盒是一个具有随机性和惊喜感,它能够激发消费者的好奇心,在拆盲盒的过程中给消费者带来巨大的愉悦感,在各种的吸引力下,消费者也愿意为各类盲盒买单。如今,随着盲…

传输线阻抗匹配电阻端接的方式

电路为什么需要端接? 众所周知,电路中如果阻抗不连续,就会造成信号的反射,引起上冲下冲、振铃等信号失真,严重影响信号质量。所以在进行电路设计的时候阻抗匹配是很重要的考虑因素。 对我们的PCB走线进行阻抗控制已经…

Python创建异步任务队列库之Huey使用详解

概要 Huey 是一个简单的 Python 库,用于创建异步任务队列。它的设计目标是简单易用,同时具备强大的功能。Huey 可以轻松地将任务添加到队列中,然后在后台线程中处理这些任务,从而避免阻塞主线程。这使得 Huey 非常适合处理 I/O 密集型或长时间运行的任务。此外,Huey 还支…

Rhino 犀牛三维建模工具下载安装,Rhino适用于机械设计广泛领域

Rhinoceros,这款软件小巧而强大,无论是机械设计、科学工业还是三维动画等多元化领域,它都能展现出其惊人的建模能力。 Rhinoceros所包含的NURBS建模功能,堪称业界翘楚。NURBS,即非均匀有理B样条,是计算机图…

JDK1.8下载、安装与配置完整图文2024最新教程

一、报错 运行Pycharm时,报错No JVM installation found. Please install a JDK.If you already have a JDK installed, define a JAVA_HOME variable in Computer >System Properties > System Settings > Environment Variables. 首先可以检查是否已安装…

如何将 Apifox 的自动化测试与 Jenkins 集成?

CI/CD (持续集成/持续交付) 在 API 测试 中的主要目的是为了自动化 API 的验证流程,确保 API 发布到生产环境前的可用性。通过持续集成,我们可以在 API 定义变更时自动执行功能测试,以及时发现潜在问题。 Apifox 支持…

PMP报考条件是什么?很多人都没读懂...

最近正值8月份考试报名期,想计划考8月份考试的宝子可以准备起来了,下面是报名时间和考试安排 8月考试时间安排: 👉报名时间在7.9日—12日 👉考试时间在8.31日(周六) 一、PMP报名条件是什么&am…

vscode插件的开发过程记录(一)

前言 本文是关于visual studio code软件上自定义插件的开发记录,将从头记录本人开发的过程,虽然网上也有很多文章,但个人在实践的过程还是会遇到不一样的问题,所以记录下来,以便于后期参考。 前期准备: 1、…

基于SpringCloud的智慧养老平台的设计与实现

您好!我是专注于计算机技术研究的码农小野。如果您对CSGO赛事管理系统感兴趣或有相关开发需求,欢迎随时联系我。 Java 数据库 MySQL 技术 SpringCloud, B/S架构 工具 Eclipse, MySQL Workbench, SpringBoot 系统展示 首页 老人管理界面 活动信息…

VBA使用ActiveWindow.Zoom调整页面显示百分比

前言 本节会通过VBA实现自动调整Excel页面显示的百分比功能 Zoom属性 1.调整当前工作表 示例:调整当前sheet显示比例为90% Sub AvtivwWindowZoom() ActiveWindow.Zoom 90 End Sub2.调整其他工作表 当一个Excel文件存在多张工作表Sheet时,又需要调…

这所985院校不保护一志愿,18人不合格被刷!西北农林科技大学计算机考研考情分析!

西北农林科技大学(Northwest A&F University),简称“西农”或“西北农林”,始创于1934年,位于中华人民共和国陕西省杨凌示范区。1999年9月11日由同处杨凌的原西北农业大学、西北林学院、中国科学院水利部水土保持研究所、水利部西北水利科…

Springboot 校园安全通事件报告小程序系统-计算机毕业设计源码02445

Springboot 校园安全通事件报告小程序系统 摘 要 随着中国经济的飞速增长,消费者的智能化水平不断提高,许多智能手机和相关的软件正在得到更多的关注和支持。其中,校园安全通事件报告小程序系统更是深得消费者的喜爱,它的出现极大…