iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >一文搞懂MySQL索引特性(清晰明了)
  • 503
分享到

一文搞懂MySQL索引特性(清晰明了)

mysql索引特性mysql索引特点mysql索引使用 2023-04-10 15:04:51 503人浏览 八月长安
摘要

目录为什么要有索引?认识磁盘磁盘的结构磁盘的盘片结构定位扇区Mysql与磁盘交互索引的理解测试主键索引索引的原理索引结构是否可以使用其他数据结构聚簇索引 vs 非聚簇索引总结为什么要有索引? MySQL索引的建立对于My

为什么要有索引?

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 查看部分数据:

一文搞懂MySQL索引特性(清晰明了)

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

一文搞懂MySQL索引特性(清晰明了)

尝试查询EMP表的记录:

一文搞懂MySQL索引特性(清晰明了)

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

为EMP表建立索引:

一文搞懂MySQL索引特性(清晰明了)

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

创建索引后尝试查询:

一文搞懂MySQL索引特性(清晰明了)

可以发现,索引大大提高了数据库表的查询速度。

认识磁盘

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

磁盘的结构

一文搞懂MySQL索引特性(清晰明了)

磁盘的盘片结构

一文搞懂MySQL索引特性(清晰明了)

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

定位扇区

一文搞懂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索引特性(清晰明了)

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

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

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

简化图:

一文搞懂MySQL索引特性(清晰明了)

索引的理解

测试主键索引

建立测试表:

一文搞懂MySQL索引特性(清晰明了)

插入多条记录:

一文搞懂MySQL索引特性(清晰明了)

查看插入结果:

一文搞懂MySQL索引特性(清晰明了)

索引的原理

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

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

伪代码:

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

一文搞懂MySQL索引特性(清晰明了)

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

引入目录后,MySQL在进行查找时,预先查找目录中的内容,对于插入数据的主键处于目录的哪一个区间,从而到区间中查找,大大提高了在单个Page中查找数据的效率。

一文搞懂MySQL索引特性(清晰明了)

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

一文搞懂MySQL索引特性(清晰明了)

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

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

一文搞懂MySQL索引特性(清晰明了)

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

总结:

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

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

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

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

一文搞懂MySQL索引特性(清晰明了)

B树 vs B+树

B树:

一文搞懂MySQL索引特性(清晰明了)

B+树:

一文搞懂MySQL索引特性(清晰明了)

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

为什么选择B+树

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

聚簇索引 vs 非聚簇索引

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

一文搞懂MySQL索引特性(清晰明了)

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

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

一文搞懂MySQL索引特性(清晰明了)

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

测试:

一文搞懂MySQL索引特性(清晰明了)

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

一文搞懂MySQL索引特性(清晰明了)

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

总结

到此这篇关于MySQL索引特性的文章就介绍到这了,更多相关MySQL索引特性内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: 一文搞懂MySQL索引特性(清晰明了)

本文链接: https://www.lsjlt.com/news/201408.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一文搞懂MySQL索引特性(清晰明了)
    目录为什么要有索引?认识磁盘磁盘的结构磁盘的盘片结构定位扇区mysql与磁盘交互索引的理解测试主键索引索引的原理索引结构是否可以使用其他数据结构聚簇索引 vs 非聚簇索引总结为什么要有索引? MySQL索引的建立对于My...
    99+
    2023-04-10
    mysql索引特性 mysql索引特点 mysql索引使用
  • 一文搞懂MySQL索引页结构
    目录1.前言2.索引页结构2.1FileHeader2.2PageHeader2.3UserRecords2.4Infimum&Supremum2.5PageDirector...
    99+
    2024-04-02
  • 一篇文章搞懂K8S高级特性
    目录K8S高级特性高级特性总结kubectl排查服务问题K8S真的放弃Docker了吗?K8S高级特性 K8S中还有一些高级特性有必要了解下,比如弹性扩缩应用(见上文)、滚动更新(见...
    99+
    2024-04-02
  • MySQL——图文版搞懂MySQL的索引是什么?
    按数据结构分类可分为:B+tree 索引、 Hash 索引、 Full-text 索引。按物理存储分类可分为:聚簇索引(主键索引)、二级索引(辅助索引)。按字段特性分类可分为:主键索引、普通索引、前缀...
    99+
    2023-10-26
    mysql 数据库
  • 一文读懂 MySQL 中的索引
    文章目录 1. 索引概述1.1 索引概述1.2 优点1.3 缺点1.6 常见索引概念1.6.1 聚簇索引1.6.2 二级索引(辅助索引、非聚簇索引)1.6.3 联合索引 1.8 MyISAM索引的原理1.9 MyISAM 与 ...
    99+
    2023-08-16
    mysql android 数据库
  • 一文带你搞懂JavaScript中数组的特性
    目录前言基本介绍数组类型和判断判断为数组的方式数组索引值和长度索引值是字符串length属性数组的最大长度创建数组的三种方式数组字面量语法Array构造函数Array.of()空位(...
    99+
    2023-05-17
    JavaScript数组特性 JavaScript数组
  • 一文弄懂MySQL索引创建原则
    目录一、适合创建索引1、字段的数值有唯一性限制2、频繁作为Where查询条件的字段3、经常Group by和Order by的列4、Update、Delete的w...
    99+
    2024-04-02
  • 一篇文章讲解清楚MySQL索引
    目录一丶什么是索引二丶索引的数据结构1.哈希表2.有序数组3.跳表4.平衡二叉搜索树5.B-树,B+树三丶InnoDB索引方案1.InnoDB行结构2.InnoDB页结构2.1行结构...
    99+
    2022-11-13
    MySQL索引 MySQL索引详解 mysql索引教程
  • 一文彻底搞清楚MySQL的主键、外键、约束和各种索引
    0.前言 主键用于唯一标识表中每一行数据,外键用于建立表与表之间关联关系,约束用于限制表中数据的规则,索引用于加速查询。 文章目录 0.前言1. 主键1.1. 在创建表时定义主键1.2. 在已有表中添加主键 2. 外键...
    99+
    2023-08-23
    mysql 数据库 sql 约束 索引
  • 一文简单了解MySQL前缀索引
    当要索引的列字符很多时 索引则会很大且变慢 ( 可以只索引列开始的部分字符串 节约索引空间 从而提高索引效率 ) 原则: 降低重复的索引值 例如现在有一个地区表 areagdpcod...
    99+
    2024-04-02
  • 一篇文章读懂什么是MySQL索引下推(ICP)
    目录一、简介 二、原理 三、实践 3.1 不使用索引下推 3.2 使用索引下推 四、使用条件 五、相关系统参数 总结一、简介 ICP(Index Condition Pushdow...
    99+
    2024-04-02
  • 一文了解MySQL二级索引的查询过程
    目录前言联合索引总结前言 聚簇索引就是innodb默认创建的基于主键的索引结构,而且表里的数据就是直接放在聚簇索引里,作为叶节点的数据页: 基于主键的数据搜索:从聚簇索引的根节点开...
    99+
    2024-04-02
  • 一文了解mysql索引的数据结构为什么要用B+树
    目录1. Hash表?No2. 二叉查找树(BST)?No3. 红黑树?No4. 平衡二叉树(AVL)?差那么二点意思5. B-tree(B-树也称B树)?差那么一点意思6. B+树...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作