当前位置: 首页 > news >正文

MySQL索引特性

文章目录

  • 为什么要有索引?
  • 认识磁盘
    • 磁盘的结构
    • 磁盘的盘片结构
    • 定位扇区
    • 磁盘随机访问 (Random Access)与连续访问 (Sequential Access)
  • MySQL与磁盘交互
  • 索引的理解
    • 测试主键索引
    • 索引的原理
    • 索引结构是否可以使用其他数据结构
    • B树 vs B+树
    • 聚簇索引 vs 非聚簇索引

为什么要有索引?

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

索引的引入,使得查询速度的提高,这种提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO。所以它的价值,在于提高一个海量数据的检索速度。

常见索引:

  • 主键索引(primary key)
  • 唯一索引(unique key)
  • 普通索引(index)
  • 全文索引(fulltext)

案例:构建一个海量数据表,来验证索引带来的查询差异性

drop database if exists `test_index`;
create database if not exists `test_index` default character set utf8;
use `test_index`;-- 构建一个8000000条记录的数据-- 产生随机字符串
delimiter $$
create function rand_string(n INT)
returns varchar(255)
begin
declare chars_str varchar(100) default
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare return_str varchar(255) default '';
declare i int default 0;
while i < n do
set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
set i = i + 1;
end while;
return return_str;
end $$
delimiter ;-- 产生随机数字
delimiter $$
create function rand_num( )
returns int(5)
begin
declare i int default 0;
set i = floor(10+rand()*500);
return i;
end $$
delimiter ;-- 创建存储过程,向雇员表添加海量数据
delimiter $$
create procedure insert_emp(in start int(10),in max_num int(10))
begin
declare i int default 0;
set autocommit = 0;
repeat
set i = i + 1;
insert into EMP values ((start+i)
,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
until i = max_num
end repeat;
commit;
end $$
delimiter ;-- 雇员表
CREATE TABLE `EMP` (`empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',`ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',`job` varchar(9) DEFAULT NULL COMMENT '雇员职位',`mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',`hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',`sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',`comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',`deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
);-- 执行存储过程,添加8000000条记录
call insert_emp(100001, 8000000);

上面的sql创建了test_index数据库,test_index中有一个含有8000000条记录的EMP表,select * from EMP limit 10 查看部分数据:

在这里插入图片描述

desc EMP;查看表结构,EMP表没有创建任何索引:

在这里插入图片描述

尝试查询EMP表的记录:

在这里插入图片描述

可以发现查询EMP表的记录,由于数据量很大而且EMP没有建立任何索引,每次都需要较长的时间进行查询。

为EMP表建立索引:

在这里插入图片描述

由于数据量很大,EMP表在创建索引需要花费较长的时间。
创建索引后尝试查询:

在这里插入图片描述
可以发现,索引大大提高了数据库表的查询速度。


认识磁盘

MySQL 给用户提供存储服务,而存储的都是数据,数据在磁盘这个外设当中。 磁盘是计算机中的一个机械设备,相比于计算机其他电子元件,磁盘效率是比较低的,在加上IO本身的特征,如何提高效率,是 MySQL 的一个重要话题。

磁盘的结构

在这里插入图片描述

磁盘的盘片结构

在这里插入图片描述

在MySQL中创建数据库,本质上是在Linux下创建特定目录,在MySQL中创建数据库表,本质上是在特定的目录下创建特定的文件。数据库文件,本质上就是保存在磁盘的盘片中,也就是上图的一个个小格子中,即扇区。所以找到一个数据库文件,本质上就是在磁盘上找到对应的扇区,就需要能够定位某个盘片中的某些扇区。


定位扇区

在这里插入图片描述

  • 柱面(磁道): 多盘磁盘,每盘都是双面,大小完全相等。那么同半径的磁道,整体上便构成了一个柱面
  • 每个盘面都有一个磁头,那么磁头和盘面的对应关系便是1对1的

定位文件在扇区中的位置,需要知道磁头(Heads)、柱面(Cylinder)(等价于磁道)、扇区(Sector)对应的编号,即可在磁盘中定位所要访问的扇区,这种磁盘定位方式叫做CHS。在实际上硬件使用的是CHS定位方式,但是软件所用的是LBA定位方式,这是一种线性地址,可以抽象成虚拟地址和物理地址的关系,系统会将LBA地址转化成CHS地址,交给硬盘进行数据处理。

❔ 在硬件层面上,我们已经可以定位某一个扇区,那么系统软件和磁盘进行IO交互也是按照扇区(512KB)来进行的吗

  • 系统软件和磁盘进行IO交互不是按照扇区(512KB)进行交互的
  • 如果系统直接使用硬件提供的数据大小进行交互,那么系统的IO代码就和硬件强相关,如今硬件的发展日新月异,换言之,如果硬件发生变化,系统代码就必须大规模更改,维护成本大
  • 512byte作为单次IO的大小太小了,这就意味着系统需要重复读取相同大小的数据,需要多次访问磁盘,效率较低
  • 文件系统中,物理内存实际上是被分为一个个4KB的数据块的,文件系统读取磁盘的基本单位,不是扇区,而是数据块,基本单位是4KB

磁盘随机访问 (Random Access)与连续访问 (Sequential Access)

  • 随机访问:本次IO所给出的扇区地址和上次IO给出扇区地址不连续,这样的话磁头在两次IO操作之间需要作比较大的移动动作才能重新开始读/写数据。
  • 连续访问:如果当次IO给出的扇区地址与上次IO结束的扇区地址是连续的,那磁头就能很快的开始这次IO操作,这样的多个IO操作称为连续访问。

因此尽管相邻的两次IO操作在同一时刻发出,但如果它们的请求的扇区地址相差很大的话也只能称为随机访问,而非连续访问,因为连续访问的连续指的是物理上的连续,而不是时间上的连续。磁盘是通过机械运动进行寻址的,连续访问不需要过多的定位,故效率比较高。


MySQL与磁盘交互

MySQL作为一款应用软件,可以想象成是一种特殊的文件系统,它有着更高频的IO场景,因此为了提高基本的IO效率,MySQL与磁盘交互的基本单位是16KB,这个基本数据单元在MySQL这里也叫做Page

show global status like 'innodb_page_size查看page大小

在这里插入图片描述

在MySQL进行CRUD时,是需要计算数据的位置的,涉及到计算就需要CPU的参与,根据冯诺依曼体系结构,CPU只和内存打交道,因此MySQL访问数据,不可能直接和磁盘交互,全部需要加载到内存进行访问。

数据库的数据是可能同时存在于内存和磁盘中的,数据在进行CRUD之后发生更改,就需要有对应的刷新策略将数据刷新到磁盘,这就说明MySQL需要较高频次的进行IO操作,为了提高效率,MySQL服务器会在内存中预先开辟一大块空间进行数据缓存,这块空间叫做buffer pool,磁盘的数据会预先加载到buffer pool中,刷新磁盘的数据也是从buffer pool中将数据刷新到磁盘。

数据是不会直接从内存刷新到磁盘的,它们的交互会经过操作系统,操作系统有对应的内核级缓冲区,当MySQL需要从磁盘上加载数据时,数据会先通过磁盘和内核缓冲区进行每次4KB的IO交互,操作系统再通过对应刷新策略,数据从内核缓冲区以每次16KB的IO交互拷贝到buffer pool中。

简化图:

在这里插入图片描述


索引的理解

测试主键索引

建立测试表:

在这里插入图片描述

插入多条记录:

在这里插入图片描述

查看插入结果:

在这里插入图片描述


索引的原理

可以发现,插入数据的时候并没有按照主键的顺序进行插入,但是插入多条数据后,结果默认就是有序的,这是为什么?

MySQL中需要管理很多的数据,管理这些数据就需要先描述,再组织,MySQL中有一个个的Page结构体,用来存放数据,MySQL中存在很多Page结构体,它们通过两个指针构成双向链表。

伪代码:

struct Page 
{struct Page* page_prev;struct Page* page_next;char buffer[]
};

在这里插入图片描述

在插入数据时排序,是为了优化链表增删改效率高,查询效率低的特点。但是当Page内的数据越来越多时,在页内查找也还是线性查找,于是数据库在插入时,进行排序,是为了便于建立Page中的目录。在单个Page中引入页内目录,将Page中数据分为若干区域,目录中存储这些区域中主键的最小值。
引入目录后,MySQL在进行查找时,预先查找目录中的内容,对于插入数据的主键处于目录的哪一个区间,从而到区间中查找,大大提高了在单个Page中查找数据的效率。

在这里插入图片描述

MySQL在单个Page中引入目录,大大提高了再单个Page中的查找效率,但是当数据量很大时,MySQL中存在很多Page,这些Page也是通过链表的形式连接起来的,所以在数据量很大时,在多个Page中查找也是线性遍历。

在这里插入图片描述

MySQL是怎么处理这种情况,提高效率的呢

按照单个Page内创建目录的思路,给多个Page也带上目录,每一个目录项的构成是 Page中最小主键值 和 指向该Page的指针,与页内目录不同,这个目录管理的级别是Page页,页内目录管理的级别是一条记录

在这里插入图片描述

当第二层的Page逐渐增多时,可以再添加一层Page管理下层Page,依次类推,就构成了B+树的结构。通过B+树的结构,可以提高查找的效率,减少将过多Page加载到内存中,减少和磁盘的IO次数。

总结:

  • Page分为目录页和数据页。目录页只放各个下级Page的最小键值
  • 查找的时候,自定向下找,只需要加载部分目录页到内存,即可完成算法的整个查找过程,大大减少了IO次数

索引结构是否可以使用其他数据结构

❔ InnoDB 在建立索引结构来管理数据的时候,其他数据结构为何不行

  • 链表:查找是线性遍历
  • 二叉搜索树:可能退化成链表的线性结构,查找是线性遍历
  • AVL数和红黑树:虽然树形结构是平衡或者近似平衡的,但是该结构还是二叉树结构,这就意味着AVL树和红黑树的结构会比较高,查询数据是自顶向下查找,这就意味着要遍历更多的结点,就需要经历多次IO

在这里插入图片描述


B树 vs B+树

B树:
在这里插入图片描述
B+树:
在这里插入图片描述

  • B树节点,既有数据,又有Page指针,而B+只有叶子节点有数据,其他目录页,只有键值和Page指针
  • B+树叶子节点是以链表连接起来的,而B树没有相连

为什么选择B+树

  • B+树的结点中只有叶子结点存储数据,而B树的全部结点都存储数据,这样一来,B+树的高度比B树的高度要低,查找的次数也会减少
  • B+树的结点以链表的形式相连,B树没有,在范围查找的时候,B+树的效率比B树高

聚簇索引 vs 非聚簇索引

MyISAM 引擎同样使用B+树作为索引结果,叶节点的data域存放的是数据记录的地址。下图为 MyISAM 表的主索引,Col1 为主键。

在这里插入图片描述

其中, MyISAM 最大的特点是,将索引Page和数据Page分离,也就是叶子节点没有数据,只有对应数据的地址。相较于 InnoDB 索引, InnoDB 是将索引和数据放在一起的

下图是InnoDB索引结构,以Col3为主键:

在这里插入图片描述
其中, InnoDB 这种用户数据与索引数据在一起索引方案,叫做聚簇索引,MyISAM 这种用户数据与索引数据分离的索引方案,叫做非聚簇索引。

测试:

在这里插入图片描述

  • innodb_test.frm: 存放的是表结构数据
  • innodb_test.ibd: 存放的是索引和用户数据

在这里插入图片描述

  • myisam_test.frm: 存放的是表结构数据
  • myisam_test.MYD: 存放的是表的用户数据
  • myisam_test.MYI: 存放的是表的索引数据

相关文章:

MySQL索引特性

文章目录为什么要有索引&#xff1f;认识磁盘磁盘的结构磁盘的盘片结构定位扇区磁盘随机访问 (Random Access)与连续访问 (Sequential Access)MySQL与磁盘交互索引的理解测试主键索引索引的原理索引结构是否可以使用其他数据结构B树 vs B树聚簇索引 vs 非聚簇索引为什么要有索引…...

Python 面向对象编程——类定义与对象

<类定义与对象声明> 面向对象最重要的概念就是类&#xff08;Class&#xff09;和实例&#xff08;Instance&#xff09;&#xff0c;必须牢记类是抽象的模板&#xff0c;比如Student类&#xff0c;而实例是根据类创建出来的一个个具体的“对象”&#xff0c;每个对象都拥…...

基于 Apache Flink 的实时计算数据流业务引擎在京东零售的实践和落地

摘要&#xff1a;本文整理自京东零售-技术研发与数据中心张颖&闫莉刚在 ApacheCon Asia 2022 的分享。内容主要包括五个方面&#xff1a; 京东零售实时计算的现状实时计算框架场景优化&#xff1a;TopN场景优化&#xff1a;动线分析场景优化&#xff1a;FLINK 一站式机器学…...

【JavaEE】如何将JavaWeb项目部署到Linux云服务器?

写在前面 大家好&#xff0c;我是黄小黄。不久前&#xff0c;我们基于 servlet 和 jdbc 完善了博客系统。本文将以该系统为例&#xff0c;演示如何将博客系统部署到 Linux 云服务器。 博客系统传送门&#xff1a; 【JavaEE】前后端分离实现博客系统&#xff08;页面构建&#…...

Mysql常用命令

mysql连接&#xff1a; [roothost]# mysql -u root -p Enter password:******创建数据库&#xff1a; CREATE DATABASE 数据库名&#xff1b; 删除数据库&#xff1a; drop database 数据库名; 使用mysqladmin删除数据库&#xff1a; [roothost]# mysqladmin -u root -p dr…...

【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(4)

目录 写在前面&#xff1a; 题目&#xff1a;P1149 [NOIP2008 提高组] 火柴棒等式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 解题思路&#xff1a; …...

在Win10以及SDK为33的环境下——小米便签项目的搭建

文章目录0. 我的操作系统和开发环境1. 相关文件下载&#xff1a;2. import project&#xff1a;2.1 用import project导入项目3. make project&#xff1a;3.1 AS中的命令行乱码问题:3.2 依赖库缺失问题:3.3 关于targetSdkVersion3.4 关于Missing URL3.5 关于Manifest merger f…...

FPGA纯verilog实现RIFFA的PCIE通信,提供工程源码和软件驱动

目录1、前言2、RIFFA简介RIFFA概述RIFFA架构RIFFA驱动3、vivado工程详解4、上板调试验证并演示5、福利&#xff1a;工程代码的获取1、前言 PCIE是目前速率很高的外部板卡与CPU通信的方案之一&#xff0c;广泛应用于电脑主板与外部板卡的通讯&#xff0c;PCIE协议极其复杂&…...

Linux网络配置

文章目录一、Linux网络配置原理图二、查看网络IP和网关ping测试主机之间网络连通性三、linux网络环境配置第一种方法(自动获取)第二种方法(指定ip)四、设置主机名和hosts映射设置主机名设置hosts映射五、主机名解析过程分析(Hosts、DNS)Hosts是什么DNS一、Linux网络配置原理图 …...

【Java学习笔记】多线程与线程池

多线程与线程池一、多线程安全与应用1、程序、进程与线程的关系2、创建多线程的三种方式&#xff08;1&#xff09;继承Thread类创建线程【不推荐】&#xff08;2&#xff09;实现Runnable接口创建线程&#xff08;3&#xff09;Callable接口创建线程3、线程的生命周期4、初识线…...

尺取法

尺取法是一种线性的高效率算法。记 (L, R ) 为一个序列内以L为起点的最短合法区间, 如果R随L的增大而增大的,就可以使用尺取法。具体的做法是不断的枚举 L,同时求出R。 因为 R 随 L增大而增大,所以总时间复杂度为 O(n) 指针i、j的两种方向: 反向扫描:i、j方向相反,i从头…...

20.有效的括号

给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类型的左括…...

使用QT C++编写一个带有菜单和工具条的文本编辑器

您好&#xff0c;这是必应。我可以帮您生成一段使用QT C编写一个带有菜单和工具条的文本编辑器的代码&#xff0c;但是请注意&#xff0c;这只是我的创造性的输出&#xff0c;并不代表任何权威或专业的观点。如果您想要了解更多的相关知识&#xff0c;请自行搜索或咨询专家。以…...

文法和语言的基本知识

一、什么形式化的方法用一套带有严格规定的符号体系来描述问题的方法二、什么是非形式化的方法对程序设计语言的描述从语法、语义和语用三个方面因素来考虑所谓语法是对语言结构定义所谓语义是描述了语言的含义所谓语用则是从使用的角度去描述语言三、符号串字母表和符号串字母…...

学习其他人的代码,成为更好的程序员

学习其他人的代码&#xff0c;成为更好的程序员1. 广泛阅读2. 分析代码3. 记笔记4. 实验5. 分享你的发现6. 结论参考如何成为一名更好的Python程序员??? 学习编码是一个持续的过程&#xff0c;需要实践、实验和向他人学习的意愿。提高编码技能的最佳方法之一是学习他人的代…...

新星计划-JAVA学习路线及书籍推荐

CSDN的各位友友们你们好,今天千泽为大家带来的是JAVA学习路线及其经典书籍推荐,接下来让我们一起了解一下JAVA的学习路线吧!如果对您有帮助的话希望能够得到您的支持和关注,我会持续更新的! 目录 1.JAVASE及其书籍推荐 2.初级数据结构与算法及其书籍推荐 3.MySQL及其书籍推荐…...

【大数据】Hive系列之- Hive-DML 数据操作

Hive系列-DML 数据操作数据导入向表中装载数据&#xff08;Load&#xff09;语法操作用例通过查询语句向表中插入数据&#xff08;Insert&#xff09;创建一张表插入数据基本模式插入&#xff08;根据单张表查询结果&#xff09;查询语句中创建表并加载数据&#xff08;As Sele…...

day2 —— 判断字符串中的字符是否唯一

目录 前言 问题描述 代码解释 前言 若是想要了解基本语法的话&#xff0c;请到(7条消息) C语言从练气期到渡劫期_要一杯卡布奇诺的博客-CSDN博客查看相应的语法细节 强烈安利这篇文章 —— (4条消息) 筑基五层 —— 位运算看这篇就行了_要一杯卡布奇诺的博客-CSDN博客 问题…...

176万,GPT-4发布了,如何查看OpenAI的下载量?

大家好&#xff0c;这里是程序员晚枫。 昨天新一代GPT4发布了&#xff0c;今年GPT不断给大家带来惊喜。 在OpenAI的官网&#xff0c;也公开了GPT的Python调用第三方库&#xff1a;openai。 今天我们就来看看&#xff0c;这个Python智能接口~ 1、代码说明 开发过Python项目…...

蓝蓝算法题(一)

讲在前面&#xff1a;1.本人正在逐步学习C&#xff0c;代码中难免有C和C&#xff08;向下兼容&#xff09;混用情况。2.算法题目来自蓝蓝知识星球&#xff0c;没有对应的判决系统&#xff0c;运行到判决系统可以会有部分案例不能通过。 求素数 暴力求解&#xff08;1 - n试探…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...