[MySQL初阶]MySQL(8)索引机制:下

标题:[MySQL初阶]MySQL(8)索引机制:下
@水墨不写bug

在这里插入图片描述


文章目录

  • 四、从问题到底层,从现象到本质
    • 1.为什么插入的数据默认排好序
    • 2.MySQL的Page
      • (1)为什么选择用Page?
      • (2)单个Page的结构(暂时)
      • (3)Mysql的多个Page的组织关系(暂时)
      • (4)页目录的引入与Page结构的修正
      • (5)多页间的情况
  • 五、B+树的引入与MySQL的InnodeDB下的索引结构
  • 六、InnodeDB为什么不选择其他的数据结构如B树?
  • 七、InnodeDB与MyISAM的索引机制区别
    • 1.存储机制不同:
    • 2.回表查询
  • 八、索引的分类
  • 九、索引的操作
    • 1.主键索引
    • 2.唯一键索引
    • 3.可重复索引(普通索引)
    • 4.索引的查询
    • 5.索引的删除
  • 十、索引创建的原则


四、从问题到底层,从现象到本质

1.为什么插入的数据默认排好序

创建如下的一张表:

create table if not exists user (
id int primary key,
age int not null,
name varchar(16) not null
);

并且按照如下的顺序插入几条数据:

insert into user (id, age, name) values(3, 18, '孙悟空');
insert into user (id, age, name) values(4, 16, '哪吒');
insert into user (id, age, name) values(2, 26, '李小龙');
insert into user (id, age, name) values(5, 36, '成龙');
insert into user (id, age, name) values(1, 56, '奶龙');

插入完成后,查询表中的数据,会发现数据已经被按照id排好序了,这是为什么?
在这里插入图片描述想要理解这个问题,就需要先明白MySQL的Page到底是什么:

2.MySQL的Page

(1)为什么选择用Page?

**IO低效的最主要矛盾不是单次IO的数据量的大小,而是IO的次数。**其次,根据局部性原理,每次IO都加载一个page,相当于预加载的一些数据,如果下次访问的数据刚好已经被加载到内存,这样效率反而可以得到提升。

(2)单个Page的结构(暂时)

单个page的结构如下:
在这里插入图片描述不同的 Page ,在 MySQL 中,都是 16KB ,使用 prev 和 next 构成双向链表。
因为有主键的问题, MySQL 会默认按照主键给我们的数据进行排序;如果没有指定主键,那么默认就会按照插入的顺序进行存储。

这就解释了为什么我们插入的数据会按照id进行排序:因为id被设置为主键。

为什么要排序?
为什么要对插入的数据进行排序?本质是为了优化查询效率。
页内部存放数据的模块,实质上也是一个链表的结构,链表的特点也就是增删快,查询修改慢,所以优化查询效率是当务之急。
正式因为有序,在查找的时候,从头到后都是有效查找,没有任何一个查找是浪费的,而且,如果运气好,是可以提前结束查找过程的!

(3)Mysql的多个Page的组织关系(暂时)

page与page之间有双向指针,

(4)页目录的引入与Page结构的修正

类比学校中教材的目录,page内部也引入的类似于目录的机制,当我们想要看某一个知识点,一定是先查书的目录,先大概确定知识点的位置,比如要看指针章节,发现在55-79页是指针相关的知识点,那么下一步就从55页开始查找想看的内容,这样就提高了查询的效率。目录会让整本书的页数增加,所以,目录是一种“以时间换空间”的做法。
另一种做法就是从开始一直向后查找,遍历整本书,这样很低效!
于是,为了提高一个page内部的查询效率,page内部的实际结构如下:
在这里插入图片描述我们要查找id=4记录,之前必须线性遍历4次,才能拿到结果。现在直接通过目录2[3],直接进行定位新的起始位置,提高了效率。
于是,MySQL自动排序的原因就是:
便于建立页目录,进而进一步提高查询效率!

(5)多页间的情况

MySQL一个page的大小为16KB,大小是固定的,然而16KB存不下大量的数据,所以必定需要多个页来存储数据:
在这里插入图片描述在单表数据不断被插入的情况下, MySQL 会在容量不足的时候,自动开辟新的Page来保存新的数据,然后通过指针的方式,将所有的Page组织起来。然而一般而言,新插入数据会修改page内的多个数据,而不是直接添加在旧数据的后面。
但是这样在Page之间的查询依然是需要遍历的,依然是很低效的!
解决方案是在现有的基础上,给每一个page也带上目录,并且把这些目录统一存放在上一级的page中:
在这里插入图片描述在上一级的page中:
存储下一级目录的索引(这个索引就是每个下一级page的最小索引);
与不同的索引不同的是,上一级page目录管理的是page,而下一级page内部的目录管理的是一行数据。
每一个目录的构成就是:键值+指针

无论是上一级page还是下一级page,本质都是page,只不过:
上一级page(目录页)存储的是下一级page(普通页)的地址;而下一级page(普通页)存储的是用户数据。

当数据进一步增多的时候,我们可以建立第三级别的page:
在这里插入图片描述通过分析,会发现上一级page不需要横向指针,因为上一级的page知识起到了路由的作用,不需要横向遍历。
查询过程分析:
根据上面的这个图示的数据结构我们想要查找主键是3的数据:
过程如下:
从最上层开始第一级目录:1 < 3 < 11 —>从1索引进入下一级page;
第二级目录: 1 < 3 < 6 —>从下标1进入下一级page;
第三级数据页:查找的3一定在这个page中:从数据索引目录2【3】找到3的这一条数据。

整个过程遍历的page的个数就是树的高度!相对于从头到尾遍历所有的page要高效非常多(3这个数据比较小,如果是查找998877这个数据行呢?);


五、B+树的引入与MySQL的InnodeDB下的索引结构

在这里插入图片描述

上图的这个结构,其实就是B+树。这也是InnodeDB的索引结构。
为什么InnodeDB选择了B+树,选择B+树的优势?
1.叶子节点保存有数据,非叶子节点没有保存数据,只保存目录项?
这样非叶子节点就可以存储更多的目录项,于是就可以管理更多的叶子page,于是可以推知:这棵树一定是一颗矮胖的树!—>查找数据行时途径的路上节点一定减少—>找到目标数据只需要更少的page,这意味着更少的IO次数---->IO层面提高了搜索的效率。
2.叶节点全都用有横向指针链接起来形成链表结构?
i,这首先是B+的特点;
ii,需要支持范围查找,一个page内的数据不一定够用。


六、InnodeDB为什么不选择其他的数据结构如B树?

链表:线性遍历----->查找非常低效,不合适;
基本的二叉搜索树----->当插入数据接近有序的时候,面临退化为线性结构,仍然会非常低效;
AVL树和红黑树:平衡二叉树---->理论上是可以的,但是二叉树只有两个树杈,分支太少,意味着相同数据量情况下,树的高度增高。与B+树的多叉树结构相比需要查找更多的page,意味着需要更多的IO交互,低效;
哈希表:O(1)直接查找---->在官方的索引实现中,MySQL是支持HASH的,仅仅是InnodeDB和MyISAM不支持。哈希虽然可以O(1)查找,但是在范围查找方面就略显无力了。
B树:B树结构与B+树不同点在于:
B树的非叶子节点既有数据,又有指针;而B+非叶子节点没有数据,只有叶子节点有数据;
B树的叶子节点没有横向指针;B+有。
结构如下:
B树:
在这里插入图片描述B+树:
在这里插入图片描述为什么选择B+?
节点不存储data,这样一个节点就可以存储更多的key。可以使得树更矮,所以IO操作次数更少。
叶子节点有横向指针相连,更便于进行范围查找。


七、InnodeDB与MyISAM的索引机制区别

1.存储机制不同:

本文前部分的把数据全都放在叶子节点的存储引擎是InnodeDB的存储引擎;除此之外,MyISAM存储引擎在叶子节点出存储的不是数据,而是数据的地址。
MyISAM存储引擎同样使用B+树,但是在叶子节点键值对数据域存储的是数据行的地址:
在这里插入图片描述聚簇索引与非聚簇索引:
把用户数据和索引数据分离存储的方案叫做非聚簇索引(如MyISAM)。
把用户数据和索引存储在一起的方案叫做聚簇索引(如InnodeDB)。
如何证明?
当我们创建一个引擎为InnodeDB数据表,发现在目录树中出现了两个文件:
在这里插入图片描述.frm:表结构;
.idb:索引和数据;

而当我们创建一个引擎为MyISAM数据表,发现在目录树中出现了三个文件:
在这里插入图片描述.frm:表结构;
.MYD:数据;
.MYI:索引结构;


2.回表查询

MySQL 除了默认会建立主键(我们没有建立主键索引的时候,InnodeDB会默认创建一个索引,来形成B+树,但是由于我们查询的条件不是默认创建的索引,所以按我们的查询条件,只能顺序遍历查找,这样通常效率非常低下)索引外,我们用户也有可能建立按照其他列信息建立的索引,一般这种索引可以叫做普通索引。
对于MyISAM而言,创建普通索引和主键索引大体没有区别(创建两个B+树,都是在叶子节点存储数据行的地址),唯一的区别就是主键不能重复,而非主键可以重复
对于InodeDB,就不一样了:InnodeDB叶子节点存储的是数据本身,而创建普通索引如果还存储数据,那就需要拷贝两份数据,这就会造成空间资源浪费。于是: InnoDB 的非主键索引中叶子节点并没有数据,而只有对应记录的key值。
所以InnodeDB通过普通索引找到目标记录需要两遍索引:
首先检索普通索引获取主键;然后通过主键在主键索引中获得数据行,这个过程称为回表查询


八、索引的分类

索引分为:主键索引、普通索引。
普通索引包括:唯一键索引、可重复的索引。

九、索引的操作

1.主键索引

创建主键索引
i,在建表的时候:

create table userA(id int primary key, name varchar(30));
create table userB(id int, name varchar(30), primary key(id));

ii,在建表之后添加:

alter table userC add primary key(id);

主键索引的特点:

一个表中只存在一个主键索引;
搜索效率高,因为主键不可重复;
主键索引的列不能为空,不可重复;
主键索引一般都是int。


2.唯一键索引

创建唯一键索引:
i,在建表的时候:

create table userD(id int primary key, name varchar(30) unique);
create table userE(id int primary key, name varchar(30), unique(name));

ii,在建表之后添加:

alter table userF add unique(name);

唯一键索引的特点:

一张表可以有多个唯一键索引;
查询效率高,不能重复;
添加唯一键索引时,这一列数据不能有重复;
唯一键+not null == 主键索引。


3.可重复索引(普通索引)

创建普通索引:
i,建表的时候

create table userG(id int primary key,name varchar(20),email varchar(30),index(name) --在表的定义最后,指定某列为索引
);

ii,创建表之后添加:

alter table userH add index(name);

iii,在表的基础上创建:

create index idx_name on userG(name);

普通索引的特点:

一张表有多个普通索引;
某一列值有重复,但是需要建立索引,就需要用到普通索引。

4.索引的查询

show keys from 表名;
show index from 表名;
desc 表名;

5.索引的删除

删除主键索引
alter table 表名 drop primary key;
删除其他索引
alter table 表名 drop index 索引名;(索引名就是show keys from 表名中的 Key_name 字段)
drop index 索引名 on 表名;

十、索引创建的原则

  • 频繁作为查询条件的字段应该为索引;
  • 唯一性太差,频繁更新的字段不适合做索引;
  • 不出现在where字句中的字段不该被创建为索引。

~完
转载请注明出处

在这里插入图片描述

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

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

相关文章

Access:在移动互联网与AI时代焕发新生

Microsoft Access&#xff1a;在移动互联网与AI时代焕发新生 在移动互联网和人工智能&#xff08;AI&#xff09;技术快速发展的今天&#xff0c;许多传统工具被认为已经过时。然而&#xff0c;Microsoft Access&#xff0c;这款曾经风靡一时的数据库&#xff0c;真的已经被淘…

【无人机】无人机PX4飞控系统高级软件架构

目录 1、概述&#xff08;图解&#xff09; 一、数据存储层&#xff08;Storage&#xff09; 二、外部通信层&#xff08;External Connectivity&#xff09; 三、核心通信枢纽&#xff08;Message Bus&#xff09; 四、硬件驱动层&#xff08;Drivers&#xff09; 五、飞…

【项目日记】高并发服务器项目总结

生活总是让我们遍体鳞伤&#xff0c; 但到后来&#xff0c; 那些受伤的地方一定会变成我们最强壮的地方。 -- 《老人与海》-- 高并发服务器项目总结 模块关系图项目工具模块缓冲区模块通用类型模块套接字socket模块信道Channel模块多路转接Poller模块 Reactor模块时间轮Tim…

Vue项目 bug 解决

Vue2项目部署失败 从gitee 上拉下一个前端项目&#xff0c;然后npm install&#xff0c;报错如下&#xff1a; 解决办法&#xff1a; 从 npm切换到cnpm&#xff1a;npm install -g cnpm执行命令export NODE_OPTIONS--openssl-legacy-provider下载依赖&#xff1a;cnpm instal…

接口自动化入门(四)

1. JMeter 的多组数据测试 1.1 使用 CSV 数据文件 JMeter 支持通过 CSV 文件提供多组测试数据&#xff0c;适用于参数化测试场景。具体步骤如下&#xff1a; 创建一个 CSV 文件&#xff0c;将测试数据以逗号分隔的形式存储。例如&#xff1a; username,passworduser1,pass1u…

企业数据分析何时该放弃Excel?

在企业数据分析中,Excel 的适用数据量范围取决于 数据复杂度、计算需求 和 硬件性能: 一、Excel 适合处理的数据量范围 数据规模适用场景限制与风险≤10万行- 日常报表 - 简单数据透视表 - 基础公式计算(如SUMIFS、VLOOKUP)处理流畅,无明显性能问题10万~50万行- 较复杂分析…

群晖NAS的最好的下载方式(虚拟机安装win系统安装下载软件)

一、背景 买NAS的其中一个用途就是下载&#xff0c;尤其是那种BT、磁力下载这种需要耗时较久的&#xff0c;开着电脑就是为了下载这种非常耗电和耗硬盘。 二、应对策略 既然有上面 “背景” 提到的痛点&#xff0c;有什么解决方式&#xff1f; NAS 上用docker安装迅雷&…

Spring AI与阿里云开发实践——生成式Java AI应用架构全解析

本文深度解析基于Spring框架与阿里云服务构建生成式AI应用的技术路径&#xff0c;涵盖架构设计、模型集成、性能优化三大维度。通过某金融企业智能客服系统实战案例&#xff0c;揭示Java生态下AI应用开发的7个关键实践要点&#xff0c;结合Gartner最新技术成熟度曲线&#xff0…

基于springboot体育俱乐部预约管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决生活上的问题&#xff0c;线上管理系统展现了其蓬勃生命力和广阔的前景。与此同时&#xff0c;在科…

找不到导入的项目“xxx\QtMsBuild\Qt.props”。请确认 Import 声明“$(QtMsBuild)\Qt.props”中计算结果为

系列文章目录 文章目录 系列文章目录前言一、问题原因 前言 新建的项目visual studio2022 使用Qt vs tools 找不到导入的项目“E:\osgEarth\DigitalSimulationPlatform\DigitalSimulationPlatform\QtMsBuild\Qt.props”。 请确认 Import 声明“$(QtMsBuild)\Qt.props”中计算结…

WPF设计标准学习记录17

在控件中的ControlTemplate的触发器 <Button Content="将ControlTemplate定义在在控件中" Width="280" Height="40" Margin="10" Foreground="#747787"><Button.Template><ControlTemplate TargetType=&quo…

【DeepSeek原理学习2】MLA 多头隐变量注意力

解决的问题 Multi-Head Latent Attention&#xff0c;MLA——解决的问题&#xff1a;KV cache带来的计算效率低和内存需求大以及上下文长度扩展问题。 MLA原理 MLA原理&#xff1a;其核心思想是将键&#xff08;Key&#xff09;和值&#xff08;Value&#xff09;矩阵压缩到…

LabVIEW 开发如何降本增效

在 LabVIEW 开发领域&#xff0c;如何在确保项目质量的同时降低开发成本&#xff0c;是众多企业和开发者共同关注的焦点。这不仅关乎资源的高效利用&#xff0c;更影响项目的投资回报率和市场竞争力。下面&#xff0c;我们将从多个维度深入剖析降本策略&#xff0c;并结合具体案…

原理图输出网表及调入

一、输出网表操作步骤 &#xff08;1&#xff09;选中.dsn文件&#xff0c;选者N或进入tools下拉列表选择Creat Netlists &#xff08;2&#xff09;导出网表后的文件 二、网表的导入 &#xff08;1&#xff09;执行菜单命令“File-Import-Logic/netlist”&#xff0c;将原理…

MyBatis 分页插件使用教程

MyBatis 分页插件使用教程 MyBatis 是一款优秀的持久层框架&#xff0c;但原生的 MyBatis 并不支持分页查询。为了简化分页操作&#xff0c;MyBatis 官方和第三方提供了多种分页插件&#xff0c;最常用的就是 MyBatis-Plus 的分页插件。本文详细介绍 MyBatis-Plus 分页插件的使…

目录穿越 + pickle反序列化 -- xyctf Signin WP

源代码 # -*- encoding: utf-8 -*-File : main.py Time : 2025/03/28 22:20:49 Author : LamentXUflag in /flag_{uuid4}from bottle import Bottle, request, response, redirect, static_file, run, route secret aapp Bottle() route(/) def index():return…

区块链技术:重塑供应链管理的未来

在当今全球化的商业环境中&#xff0c;供应链管理的复杂性和重要性日益凸显。从原材料采购到产品交付&#xff0c;供应链的每一个环节都可能影响企业的运营效率和客户满意度。随着区块链技术的兴起&#xff0c;供应链管理迎来了新的变革机遇。本文将深入探讨区块链技术在供应链…

ragflow本地部署(WSL下Ubuntu)

本地docker及 docker-compose版本 安装参考&#xff1a; 实践笔记-docker安装及配置镜像源实践笔记-docker-compose安装 1.下载源码 git clone https://github.com/infiniflow/ragflow.git2.运行docker-compose拉取镜像 cd ragflow/docker docker-compose up -d3.启动报错…

LTSPICE仿真电路:(二十六)跨阻放大器简单仿真

1.前言 由于有个机会刚好了解了下跨阻&#xff0c;简单做个这个仿真&#xff0c;实际上跨阻放大器应该要复杂的多&#xff0c;由于跨阻放大器实际上是将电流转换为电压&#xff0c;最需要注意的参数肯定是运放的偏置电流 2.跨阻放大器仿真 这篇是纯记录 这是一个将0-50uA电流…

androd的XML页面 跳转 Compose Activity 卡顿问题

解决 XML 点击跳转到 Compose Activity 卡顿问题 当从 XML 布局的 Activity 跳转到 Compose Activity 时出现卡顿现象&#xff0c;这通常是由以下几个原因导致的&#xff1a; 可能的原因及解决方案 1. Compose 首次初始化开销 问题&#xff1a;Compose 框架首次初始化需要时…