【Hello mysql】 mysql的索引(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 【Hello mysql】 mysql的索引

索引

索引是什么

课件上对于索引的定义是这样子的

索引:提高数据库的性能,索引是物美价廉的东西了。不用加内存,不用改程序,不用调sql,只要执行正确的 create index ,查询速度就可能提高成百上千倍。但是天下没有免费的午餐,查询速度的提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的IO。所以它的价值,在于提高一个海量数据的检索速度。

总结下上面这段话

索引是mysql的一个特性 使用它可以增加mysql的查找效率 但是可能会牺牲一部分IO效率

索引的分类

常见的索引分类如下

  • 主键索引(primary key)
  • 唯一索引(unique)
  • 普通索引(index)
  • 全文索引(fulltext)–解决中子文索引问题

关于这个分类 大家现在不理解也没关系 等看完整篇博客之后就能对于它们有一个清晰的认知

索引作用查看

我们这里创建一张海量数据的数据库表(八万条数据) 演示在有和没有索引的情况下 效率的差别

我们可以使用下面的sql来创建一个海量数据表 (直接复制粘贴到mysql终端即可)

drop database if exists `index_demon`;
create database if not exists `index_demon` default character set utf8;
use `index_demon`;
-- 构建一个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中创建了一个名为index_demon的数据库 在该数据库中创建了一个名为EMP的员工表 并向表当中插入了八百万条记录

建立该数据库需要大概七分钟左右的时间 大家耐心等待

创建完毕之后我们即可使用index_demo数据库和里面的EMP表 下面开始我们的对比工作

查询员工编号为998877编号的员工

我们可以发现 花费了4.35秒才找到了该条记录

创建索引

对这八百万条记录创建索引我们用了20.33秒

重新查询该员工的数据

重新查询之后进步十分明显 直接从4.35秒降低到了0秒

这里就说明一个道理 索引对于海量数据查询效率的提升是十分显著的

磁盘

mysql的工作过程

宏观过程

由于冯诺伊曼体系我们可以知道 mysql不能对于磁盘中的数据库进行直接访问 它的访问一定是要经过操作系统的内核缓冲区的

大概的运行过程如上图

  1. mysql在内存中申请一大块内存空间 我们一般叫做buff pool
  2. mysql对于数据的curd都是在内存中进行操作的
  3. mysql调用系统函数write之后这些数据会写入操作系统的内核缓冲区当中
  4. 操作系统的内核缓冲区会定期刷新数据到磁盘中的数据库

认识磁盘

磁盘的整体结果如下

我们再来看看磁盘中的一个盘片

盘片中又被分为磁道和扇区 如上图所示 我们这里对于磁盘的整体结构和扇区概念有一个认知即可

其中扇区的大小大部分都是512字节

而我们前面说过 数据库的文件都保存在磁盘当中 所以说我们查找数据的本质就是在定位扇区

定位扇区

我们在硬件层面定位扇区的方式叫做CHS

  1. 首先找到磁头来确定文件在哪一个盘面
  2. 之后在该盘面中找到数据所在的磁道
  3. 最后在磁道中找到对于的扇区

但是在软件层面上我们使用的定位方式叫做LBA(一种线性地址) 我们可以把它们之间的关系想象成虚拟地址和物理地址之前的关系来方便理解

在软件层面上通过LBA定位到以后最终还是要使用CHS来定位具体的物理空间

操作系统和磁盘交互的基本单位

我们现在已经能够在硬件层面定位扇区了 那么在系统软件上我们就直接按照扇区的基本单位(大部分512字节)进行交互嘛?

答案是否定的 原因有以下几点

  • 如果操作系统使用硬件提供的基本单位进行交互 那么操作系统和硬件之间就会产生强相关的关系 一旦硬件发生大的改变 操作系统势必也要发生改变
  • 我们都知道 IO的效率是非常非常慢的 单次IO512字节还是太小了 而每次读取很小的数据势必会造成更多次的IO
  • 我们在基础IO时学习文件系统 文件系统就是在磁盘的基本结构下建立的 而它的基本单位不是扇区 而是数据块

综上所述 系统读取磁盘是以块为单位的 大小为4kb

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

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

因此尽管相邻的两次IO操作在同一时刻发出,但如果它们的请求的扇区地址相差很大的话也只能称为随机访问,而非连续访问。

磁盘是通过机械运动进行寻址的,随机访问不需要过多的定位,故效率比较高。

mysql和磁盘交互的基本单位

mysql和磁盘交互这句话其实并不准确 因为mysql没有资格直接和磁盘进行交互 它们之间一定是要经过操作系统的 但是我们学习这部分的时候为了方便理解可以暂时忽略操作系统

MySQL 作为一款应用软件,可以想象成一种特殊的文件系统。它有着更高的IO场景,所以为了提高基本的IO效率, MySQL 进行IO的基本单位是 16KB (后面统一使用 InnoDB 存储引擎讲解)

我们可以使用下面的sql语句来查看mysql交互的IO大小 我们可以发现是16384字节 实际也就是16kb

根据上面讲解的知识总结一些共识

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

如何理解IO请求

首先我们可以明确一点 系统中肯定会存在大量的IO请求 而操作系统作为软硬件资源的管理者肯定要对这些资源进行管理 那么问题又来了 应该如何管理呢? - - 先描述 再组织

我们都知道Linux操作系统是由C语言写的 而C语言中描述一个对象所使用的方式是结构体

所以说IO请求在Linux操作系统中的形式其实就是结构体 这些结构体再被通过双链表的形式组织起来 这就是操作系统对于IO请求的管理

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
196 66
|
16天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
117 9
|
20天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
60 18
|
13天前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
48 8
|
19天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
22 7
|
18天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
50 5
|
22天前
|
存储 关系型数据库 MySQL
Mysql索引:深入理解InnoDb聚集索引与MyisAm非聚集索引
通过本文的介绍,希望您能深入理解InnoDB聚集索引与MyISAM非聚集索引的概念、结构和应用场景,从而在实际工作中灵活运用这些知识,优化数据库性能。
98 7
|
8天前
|
存储 关系型数据库 MySQL
【MYSQL】 ——索引(B树B+树)、设计栈
索引的特点,使用场景,操作,底层结构,B树B+树,MYSQL设计栈
|
2月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
53 2
|
2月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
341 1