【Hello mysql】 mysql的索引(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 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请求的管理

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
15天前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
29天前
|
SQL 关系型数据库 MySQL
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
|
23天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
56 3
Mysql(4)—数据库索引
|
17天前
|
存储 关系型数据库 MySQL
如何在MySQL中进行索引的创建和管理?
【10月更文挑战第16天】如何在MySQL中进行索引的创建和管理?
41 1
|
6天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
38 0
|
7天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
34 0
|
19天前
|
监控 关系型数据库 MySQL
mysql8索引优化
综上所述,深入理解和有效实施这些索引优化策略,是解锁MySQL 8.0数据库高性能查询的关键。
27 0
|
22天前
|
SQL 关系型数据库 MySQL
美团面试:mysql 索引失效?怎么解决? (重点知识,建议收藏,读10遍+)
本文详细解析了MySQL索引失效的多种场景及解决方法,包括破坏最左匹配原则、索引覆盖原则、前缀匹配原则、`ORDER BY`排序不当、`OR`关键字使用不当、索引列上有计算或函数、使用`NOT IN`和`NOT EXISTS`不当、列的比对等。通过实例演示和`EXPLAIN`命令分析,帮助读者深入理解索引失效的原因,并提供相应的优化建议。文章还推荐了《尼恩Java面试宝典》等资源,助力面试者提升技术水平,顺利通过面试。
|
26天前
|
关系型数据库 MySQL 数据库
深入浅出MySQL索引优化:提升数据库性能的关键
在这个数据驱动的时代,数据库性能的优劣直接关系到应用的响应速度和用户体验。MySQL作为广泛使用的数据库之一,其索引优化是提升查询性能的关键。本文将带你一探MySQL索引的内部机制,分析索引的类型及其适用场景,并通过实际案例演示如何诊断和优化索引,以实现数据库性能的飞跃。
|
27天前
|
SQL 存储 关系型数据库
MySQL新增字段/索引会不会锁表?
MySQL新增字段/索引会不会锁表?