MySQL--索引--0427--0507

news2024/11/28 2:43:44

目录

1. MySQL是如何处理数据的

2. MySQL与磁盘的关系

 3. MySQL与磁盘交互的基本单位

 4.MySQL和磁盘之间联系的总结

 5.索引的理解

5.1 理解单个page

 5.2 理解多个page

5.3 为什么采用B+树

5.4 聚簇索引 和 非聚簇索引

5.5 聚簇索引 和 非聚簇索引下的普通索引

6.索引操作

6.1 创建主键索引

 6.2 创建唯一索引

6.3 创建普通索引

6.4 查询索引

6.5 删除索引

6.6 全文索引

7.复合索引

7.1 最左匹配原则

8.索引覆盖


1. MySQL是如何处理数据的

MySQL 中的数据文件,是以page为单位保存在磁盘当中的。找到了对应的扇区之后呢?

MySQL 的 CURD 操作,都需要通过计算,找到对应的插入位置,或者找到对应要修改或者查询的数据,谁又可以帮助计算呢?

2. MySQL与磁盘的关系

mysqld本质上就是一个在应用层的进程,所以他一定在操作系统之上运行的。当MySQL对内部的数据进行操作(CURD)的时候,本质上就是操作文件内容。所以文件必须先被打开,在哪里打开呢?难道是磁盘吗?肯定不是,文件需要被加载到内存当中,才能被同在内存中的进程获取到。

如果数据不在内存中呢?换入换出。换出来的内容放在哪里呢?所以mysql内部一定管理有一块空间,用来读取存放在内核缓冲区中的数据,不然每次都要开辟空间。所以在MySQL启动的时候,要预先申请一批空间。

 3. MySQL与磁盘交互的基本单位

MySQL本身就是用来处理数据的,所以少不了和磁盘进行接触。磁盘扇区大小为512字节,为了避免大量IO,以及减少耦合,文件系统读取以块为单位读取磁盘数据,单位是4KB。而MySQL进行IO的基本单位是16KB,这个基本数据单元称为page(和系统的page不一样)。

所以MySQL一次读取,就会至少读4个linux kernel,也就是4*8个扇区。

为何MySQL和磁盘进行IO交互的时候,要采用Page的方案进行交互呢?用多少,加载多少可以吗?
如过有5条记录,如果MySQL要查找id=2的记录,第一次加载id=1,第二次加载id=2,一次一条记录,那么就需要2次IO。如果要找id=5,那么就需要5次IO。
但如果这5条都被保存在一个Page中(16KB,能保存很多记录),那么第一次IO查找id=2的时
候,整个Page会被加载到MySQL的Buffer Pool中,这里完成了一次IO。但是往后如果在查找id=1,3,4,5等,完全不需要进行IO了,而是直接在内存中进行了。所以,就在单Page里面,大大减少了IO的次数。

MySQL申请的缓冲区中基本IO单位为page,说明内部一定有很多page,那么也就需要他来管理这些数据,用什么样的数据结构管理这些数据,也就是建立索引之后搜索变快的基础。

 4.MySQL和磁盘之间联系的总结

  • MySQL 中的数据文件,是以page为单位保存在磁盘当中的。
  • MySQL 的 CURD 操作,都需要通过计算,找到对应的插入位置,或者找到对应要修改或者查询的数据。而只要涉及计算,就需要CPU参与,而为了便于CPU参与,一定要能够先将数据移动到内存当中。
  • 所以在特定时间内,数据一定是磁盘中有,内存中也有。后续操作完内存数据之后,以特定的刷新策略,刷新到磁盘。而这时,就涉及到磁盘和内存的数据交互,也就是IO了。而此时IO的基本单位就是Page。
  • 为了更好的进行上面的操作, MySQL 服务器在内存中运行的时候,在服务器内部,就申请了被称为 Buffer Pool 的的大内存空间,来进行各种缓存。其实就是很大的内存空间,来和磁盘数据进行IO交互。
  • 为何更高的效率,一定要尽可能的减少系统和磁盘IO的次数
     

 5.索引的理解

建立一张有主键的表,然后随便插入几条数据。

mysql> desc t1;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| age   | int(11)     | YES  |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
mysql> insert into t1 values(3,18,'杨过');
mysql> insert into t1 values(4, 16, '小龙女');
mysql> insert into t1 values(2, 26, '黄蓉');
mysql> insert into t1 values(5, 36, '郭靖');
mysql> insert into t1 values(1, 56, '欧阳锋');
mysql> select * from t1;
+----+------+-----------+
| id | age  | name      |
+----+------+-----------+
|  1 |   56 | 欧阳锋    |
|  2 |   26 | 黄蓉      |
|  3 |   18 | 杨过      |
|  4 |   16 | 小龙女    |
|  5 |   36 | 郭靖      |
+----+------+-----------+

 现象:我并没有按照主键大小的顺序进行插入,但是在表中这些数据已经按照一定顺序帮我排列好了。

谁做的?mysql自己做的。

为什么做?只有page里面的数据是有序的,才能方便的引入页内目录(后面说),才能加快查找速度。

5.1 理解单个page

先描述,在管理

但是当我单个page内的数据非常多,每次查找一个就要遍历一遍链表吗?使用二分?

加一个页内目录即可,就像书籍前面的目录一样,方便读者查找文章内容。

在单个页中存放了多条数据信息,从而避免了频繁的IO操作,大大加快了搜索速度。可我怎么知道我需要的数据就在这个page,而不是前一个或者后一个呢?

 5.2 理解多个page

如果真的采用上述双链表样的结构存储数据,由于链表的遍历是O(n)的,找对应的page需要遍历一遍,那效率也太低了。

所以我们需要将页内目录也扩展到page与page之间。

  • 使用一个目录项来指向某一页,而这个目录项存放的就是将要指向的页中存放的最小数据的键值。
  • 和页内目录不同的地方在于,这种目录管理的级别是页,而页内目录管理的级别是行。
  • 其中,每个目录项的构成是:键值+指针。

存在一个目录页来管理页目录,目录页中的数据存放的就是指向的那一页中最小的数据。有数据,就可通过比较,找到该访问那个Page,进而通过指针,找到下一个Page。

目录页的本质也是页

普通页中存的数据是用户数据,而目录页中存的数据是普通页的地址。

目录页所在结构无需加前后指针,因为

只有相邻的普通页由于连续存储,一个page存不下了,需要创建第二个page,这样两个page使用前后指针方便了查找,而无需再从类似根节点的地方再走一遍。

目录页不存数据,因为

虽然存数据可以方便某一些查找情况下直接返回数据,但是如果页目录没有数据,就意味着16KB的空间全部可以用来保存(id,page_address),会让这颗树变得矮胖,所以走到叶子节点所经历的中间节点就少了,也就意味着IO的次数少了,所以更快了。

 综上,存储的结构已经显现,就是B+树。

5.3 为什么采用B+树

链表——线性遍历,太慢。

二叉搜索树——退化问题,而且是二叉,树层高。

AVL、红黑树——再平衡也是二叉树,树层高。

Hash——MySQL其实支持Hash,不过 InnoDB 和 MyISAM 并不支持,在面对范围查找就明显不行

B树

 可以发现B树会在近似页目录的机构中添加数据。即B树的节点既有数据、又有page指针,叶子节点有键值和数据。

B+树

 

而B+树只有叶子节点有数据,其他目录页,只有键值和page指针,可以使树更矮,减少了IO次数。而且叶子节点相连,更有利于进行范围查找。

5.4 聚簇索引 和 非聚簇索引

二者底层存储结构都是B+树,但是存储的数据内容不一样。

MyISAM存储引擎,叶节点的数据域存放的是数据记录的地址。

 MyISAM最大的特点就是将索引page和数据page分离,叶节点只有对应数据的地址。

而InnoDB是将索引和数据放在一起的。

MyISAM 这种用户数据与索引数据分离的索引方案,叫做非聚簇索引

mysql> create table mtest(id int primary key,
        name varchar(11) not null)engine=MyISAM;

mtest.frm  表的数据结构
mtest.MYD 该表对应的数据,现在没插入数据 所以是0
mtest.MYI  该表对应的主键索引


InnoDB 这种用户数据与索引数据在一起索引方案,叫做聚簇索引

mysql> create table itest(id int primary key,
        name varchar(11) not null)engine=InnoDB;

itest.frm 表结构数据
itest.ibd  该表对应的主键索引和用户数据,虽然没有数据 但是有主键索引,所以不是0

5.5 聚簇索引 和 非聚簇索引下的普通索引

MyISAM ,建立普通索引和主键索引没有差别,无非就是主键不能重复,而非主键可重复。以第二列建立索引。
 

 InnoDB 除了主键索引,用户也会建立普通索引

InnoDB 的非主键索引中叶子节点并没有数据,而只有对应记录的key值。
所以通过普通索引,找到目标记录,需要两遍索引:首先检索辅助索引获得主键,然后用主键
到主索引中检索获得记录。这种过程,就叫做回表查询。

6.索引操作

6.1 创建主键索引

在建表的时候,创建主键,自动建立主键索引。

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


create table user3(id int, name varchar(30));
alter table user3 add primary key(id)

主键索引名字为PRIMARY

 6.2 创建唯一索引

创建唯一键时自动建立唯一索引

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

create table user6(id int primary key, name varchar(30));
alter table user6 add unique(name);

 唯一索引名为列名

6.3 创建普通索引

在表的定义最后,指定某列为索引

create table user8(id int primary key,
        name varchar(20),
        email varchar(30),
        index(name));

创建完表以后指定某列为普通索引

create table user9(id int primary key, name varchar(20), 
                email varchar(30));
alter table user9 add index(name);
mysql> desc user9;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| name  | varchar(20) | YES  | MUL | NULL    |       |
| email | varchar(30) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

创建一个索引名为 idx_name 的索引

create table user10(id int primary key, name varchar(20), 
        email varchar(30));
create index idx_name on user10(name);

注意:

  • 建立普通索引默认,索引名字和列名字相同。
  • 如果给普通索引起别名,删除时需要指定该别名。

6.4 查询索引

show index from 表名;

mysql> show index from user10;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user10 |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| user10 |          0 | email    |            1 | email       | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
| user10 |          1 | name     |            1 | name        | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

6.5 删除索引

删除主键索引

alter table 表名 drop primary key;

其他索引的删除

alter table 表名 drop index 索引名;

 其他写法

drop index 索引名 on 表名;

6.6 全文索引

当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。MySQL提供全文索引机制,但是有要求,要求表的存储引擎必须是MyISAM,而且默认的全文索引支持英文,不支持中文。

查询有没有database数据

如果采用以下查询方式,虽然有结果但是没有用到全文索引。

mysql> select * from articles where body like '%database%';

使用全文索引

mysql> SELECT * FROM articles
    -> WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
+----+-------------------+------------------------------------------+

7.复合索引

相当于在键值中比较的是(col1,col2),名字和col1的列名相同。先比较col1,在比较col2。

7.1 最左匹配原则

CREATE INDEX IDX_XXX ON TABLE(COL3, COL2);

 

详见

复合索引的底层数据结构——最左原则_复合索引在底层的数据结构是什么_长不大的大灰狼的博客-CSDN博客

8.索引覆盖

通俗来说,就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。

比如

id为聚集索引,name为非聚集索引:

select name, age from t where name = 'chy';

由于select后面有name 和 age,此时就需要回表查询。

但是如果在SQL中只查询name字段。这样name的索引就覆盖到了所有的查询列。

select name from t where name = 'chy';

或者将name的索引修改为联合索引(name, age )

select name, age from t where name = 'chy';

这样也覆盖到了所有的查询列。

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

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

相关文章

Spring 注解之@RestController与@Controller的区别

目录 1:介绍 2:区别 3:总体来说 4:社区地址 1:介绍 RestController 和 Controller 是 Spring MVC 中常用的两个注解,它们都可以用于定义一个控制器类。 2:区别 返回值类型不同:…

STM32单片机声控语音识别RGB彩灯多种模式亮度可调WS2812彩灯

实践制作DIY- GC0129-语音识别RGB彩灯 一、功能说明: 基于STM32单片机设计-语音识别RGB彩灯 二、功能介绍: STM32F103C系列最小系统板5VUSB电源64个灯珠的WS2812灯板1个开关键(3档亮度调节)1个模式切换键(白灯 红灯…

软件测试4年从外包15K跳槽去字节 38K+12,啃完这份笔记你也可以

转行做软件测试已经是第4个年头,一直是一个不温不火的小职员,本本分分做着自己的事情,觉得自己的工作已经遇到了瓶颈,一个偶然的机会,获得了一份软件测试全栈知识点学习笔记,通过几个月的学习,5…

git提交代码到GitLab步骤及拉取远程分支内容

一、本地建立一个空文件夹 点击鼠标右键点击红色箭头方向 Git Hash Here 二、git init 进行初始化 这个时候文件夹中会出现 .git 文件夹 三、添加远程仓库地址 git remote add origin (address) # 添加远程仓库地址 address是远程仓库代码链接 四、如果有分支把远程分支拉到…

跨设备开发的未来:多端能力服务统一技术

多端能力服务统一(Multi-Experience Service Orchestration,MESO)是一种技术和服务架构的概念,旨在为多种终端设备提供统一的用户体验和功能。它解决了在不同终端设备上使用不同应用程序和服务时出现的问题,使得用户可…

Springboot +Flowable,会签、或签简单使用(二)

一.简介 **会签:**在一个流程中的某一个 Task 上,这个 Task 需要多个用户审批,当多个用户全部审批通过,或者多个用户中的某几个用户审批通过,就算通过。 例如:之前的请假流程,假设这个请假流程…

[iOS]消息传递和消息转发

消息转发和消息传递 消息转发 iOS的消息转发是指当一个对象收到一个无法响应的消息时,其会通过多个方法转发该消息,直到能够响应为止。具体来说,当消息接收者无法响应某个方法时,Objective-C消息传递机制会按照以下顺序进行转发…

路径规划算法:基于绯鲵鲣算法的路径规划算法- 附代码

路径规划算法:基于绯鲵鲣优化的路径规划算法- 附代码 文章目录 路径规划算法:基于绯鲵鲣优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要:本文主要介绍利用智能优化算法…

java读取word文档内容

首先在pom文件引入依赖&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.0.0</version> </dependency> <dependency><groupId>org.apache.poi</groupId&g…

Databend 开源周报第 93 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 改进 Databend …

冠珠华珍岩板闪现人民日报美好博物馆,彰显民族品牌魅力

行业唯一&#xff01;亮相美好博物馆 一块为中国品牌发声 为了贯彻落实品牌强国战略&#xff0c;展现中国优秀品牌成果&#xff0c;5月10日&#xff0c;值第7个中国品牌日来临之际&#xff0c;由人民日报社特别打造的美好博物馆主题快闪店惊艳亮相上海世博展览中心。 作为连…

【 LoRa规范及认证】

文章目录 LoRa规范及认证一、LoRaWAN全球区域规范1.美国规范2.中国规范 二、LoRaWAN认证1.LoRaWAN认证常见问题 三、中国LoRa无线电规范四、小结 LoRa规范及认证 ​ 在使用LoRa设备时&#xff0c;必须遵循各区域无线电管理规范&#xff0c;尤其是工作频率、输出功率、占空比这…

万字长文 | ChatGPT的工作原理(二)

— 6 — 嵌入的概念 神经网络 —— 至少在它们目前的设置中 —— 从根本上说是基于数字的。因此&#xff0c;如果我们要用它们来处理像文本这样的东西&#xff0c;我们就需要一种方法来用数字表示我们的文本。 当然&#xff0c;我们可以开始&#xff08;基本上就像 ChatGPT 那…

Java基础面试题突击1

&#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我不迷路 ❤️《java面试核心知识》突击系列&#xff0c;持续更新… &#x1f490; 面试必知必会学习路线&#xff1a;Java技术栈面试系列SpringCloud项目实战学习路线 &#x1f4dd;再小的收获*365天…

物流管理系统对电商的重要性,零代码技术起关键性作用

什么是物流管理系统 物流管理系统是一种软件系统&#xff0c;用于管理和协调货物的移动。它涵盖了物流计划、物流执行、物流跟踪和数据分析等方面&#xff0c;可以帮助企业优化供应链&#xff0c;提高运营效率和客户满意度。它包括了仓储管理、配送管理、运输管理、订单管理、…

编织数据结构的艺术:双向带头循环链表的华丽实现

上一篇博客&#xff0c;我们了解并实现了单向不带头不循环链表&#xff0c;而本篇博客会讲解链表中的王者&#xff1a;双向带头循环链表。 概述 双向带头循环链表的特点是&#xff1a; 每个结点内部&#xff0c;既有指向上一个结点的前驱指针prev&#xff0c;也有指向下一个…

《C++入门攻略》(小白向)

函数 函数、输入、传参 在程序中使用函数时&#xff0c;你必须先声明它然后再定义声明的目的是告诉编译器你即将要定义的函数的名字是什么&#xff0c;返回值的类型是什么以及参数是什么而定义则是告诉编译器这个函数的功能是什么。假如我们不声明&#xff0c;那么该函数就不能…

vue快速上手教程与简单安装

目录 vue简介 vue实例 通过 CDN 使用 Vue NPM 方法 介绍 下载 使用 vue简介 Vue.js 是一套构建用户界面的渐进式框架。 Vue 只关注视图层&#xff0c; 采用自底向上增量开发的设计。 Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 vue实例…

ping包过程之arp(地址解析协议)

0,怎么引出arp地址解析协议的呢&#xff1f; 在硬件层次上进行的数据帧交换必须有正确的接口地址&#xff08;既是MAC地址&#xff09;。但是&#xff0c; T C P / I P有自己的地址&#xff1a; 32 bit的I P地址。知道主机的 I P地址并不能让内核发送一帧数据给主机。内核&…

二十、Zipkin持久化链路跟踪

目录 Zipkin持久化 使用mysql数据库持久化 1、创建zipkin数据库 2、启动zipkin使用以下脚本 3、访问接口&#xff08;配置了sleuth链路跟踪&#xff09; 使用ElasticSearch持久化 zipkin启动脚本 Zipkin持久化 Zipkin server默认会将追踪数据信息保存在内存中&#xff0…