mysql---索引特征 (重要)

1.索引的概念

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

当然索引也不例外;而索引之所以可以提高效率,本质上是改变了组织数据的方式;而我们的mysqld其实就是我们的进程,而索引其实就是进程中的一种数据结构;

2.索引的分类

3.见一见索引

先整一个海量表,在查询的时候,看看没有索引时有什么问题?

这个数据库的表里面有800万条我们生成的随机数;

现在我们来用以前的方法查一下具体的empno看看是否能查到;

我们查了几次发现几乎在5sec附近,这样的效率很低,因此我们就需要加索引了;

现在我们再去查找就发现时间变得非常快了;

4.索引的本质(就是B+的数据结构)

4.1mysql的存储

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

4.2mysql中数据访问的理解

数据库文件,本质其实就是保存在磁盘的盘片当中,就是一个一个的文件;所以,最基本的,找到一个文件的全部,本质上就是在磁盘找到所有保存文件的扇区。而我们能够定位任何一个扇区,那么便能找到所有扇区,因为查找方式是一样的。

柱面==盘面(因为一个一个的盘累积起来成为了柱)

盘片在转动,磁头在左右摆动;

柱面==磁道

4.2.1定位扇区

++"定位一个文件的过程为;磁头->磁道->扇区(CHS)++

4.2.2 系统定位

不过实际系统软件使用的并不是 CHS (但是硬件是),而是 LBA ,一种线性地址,可以想象成虚拟地址与物理地址。系统将 LBA 地址最后会转化成为 CHS ,交给磁盘去进行数据读取。

4.3 数据库文件如何进行IO交互

在硬件层面定位任何一个基本数据块其实就是定位扇区。那么在系统软件上,就直接按照扇区(512字节,部分4096字节),进行IO交互吗?不是

如果操作系统直接使用硬件提供的数据大小进行交互,那么系统的IO代码,就和硬件强相关,换言之,如果硬件发生变化,系统必须跟着变化;从目前来看,单次IO 512字节,还是太小了。IO单位小,意味着读取同样的数据内容,需要进行多次磁盘访问,会带来效率的降低。

之前学习文件系统,就是在磁盘的基本结构下建立的,文件系统读取基本单位,就不是扇区,而是数据块。所以系统读取磁盘,是以块为单位的,基本单位是 4KB

4.4 磁盘随机访问与连续访问

随机访问:本次IO所给出的扇区地址和上次IO给出扇区地址不连续,这样的话磁头在两次IO操作之间需要作比较大的移动动作才能重新开始读/写数据。

连续访问:如果当次IO给出的扇区地址与上次IO结束的扇区地址是连续的,那磁头就能很快的开始这次IO操作,这样的多个IO操作称为连续访问。

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

4.5 MySQL 与磁盘交互基本单位

而 MySQL 作为一款应用软件,可以想象成一种特殊的文件系统。它有着更高的IO场景,所以,为了提高基本的IO效率,**MySQL 进行IO的基本单位是 16KB ;**也就是说,磁盘这个硬件设备的基本单位是 512 字节,而 MySQL InnoDB引擎 使用 16KB 进行IO交互。

所以 MySQL 和磁盘进行数据交互的基本单位是 16KB 。这个基本数据单元,在 MySQL 这里叫做page;

4.6 Buffer Pool

MySQL 中的数据文件,是以page为单位保存在磁盘当中的。

MySQL 的 CURD 操作,都需要通过计算,找到对应的插入位置,或者找到对应要修改或者查询数据。

而只要涉及计算,就需要CPU参与,而为了便于CPU参与,一定要能够先将数据移动到存当中。 所以在特定时间内,数据一定是磁盘中有,内存中也有。后续操作完内存数据之后,以定的刷新策略,刷新到磁盘。而这时,就涉及到磁盘和内存的数据交互,也就是IO了。而此时IO基本单位就是Page。

为了更好的进行上面的操作, MySQL 服务器在内存中运行的时候,在服务器内部,就申请了被称为 Buffer Pool 的的大内存空间,来进行各种缓存 。其实就是很大的内存间来和磁盘数据进行IO交互。为了更高的效率,一定要尽可能的减少系统和磁盘IO的次数;

5.索引的底层

5.1测试

首先插入多条数据

查看插入结果

我们发现竟然默认是有序的!是谁干的呢?排序有什么好处呢?

为什么数据库在插入数据时要对其进行排序呢?我们按正常顺序插入数据不是也挺好的吗?
插入数据时排序的目的,就是优化查询的效率。页内部存放数据的模块,实质上也是一个链表的结构,链表的特点也就是增删快,查询修改慢,

所以优化查询的效率是必须的。正是因为有序,在查找的时候,从头到后都是有效查找,没有任何一个查找是浪费的,而且,如果运气好,是可以提前结束查找过程的;嘿嘿,读到后面你就会发现其实是为了引入页目录;

5.2 为何IO交互为Page

用多少,加载多少不好吗?

如果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的次数。你怎么保证,用户一定下次找的数据,就在这个Page里面?我们不能严格保证,但是有很大概率,因为有

局部性原理:一次加载的数据,下一次很有可能在上次数据的附近,即为局部性原理

往往IO效率低下的最主要矛盾不是IO单次数据量的大小,而是IO的次数。

5.3 理解单个page

理解单个PageMySQL 中要管理很多数据文件,而要管理好这些文件,就需要 先描述,在组织 ,我们目前可以简单理解成一个个独立文件是有一个或者多个Page构成的。

不同的 Page ,在 MySQL 中,都是 16KB ,使用 prev 和 next 构成双向链表;因为有主键的问题, MySQL 会默认按照主键给我们的数据进行排序,从上面的Page内数据记录可以看出,数据是有序且彼此关联的

5.4 理解多个page

通过上面的分析可知,页模式的核心思想是:在查询某条数据时,将一整页数据加载到内存,以减少硬盘I/O次数,从而提升性能。然而,页模式内部实际上仍采用链表结构------数据之间通过指针逐条链接,本质上还是在做逐条比较查找。

试想,如果有1000万条数据,势必分布在多个页中,页之间通过双链表连接,每个页内部也是链表结构。那么,要查找某条特定记录,依然需要线性遍历。这样的效率,显然太低了

5.4.1页目录(又叫页内目录)

比如我们在阅读一本书的时候,需要查看具体的某一个章节,我们最高效的方法是查询目录,而我们的数据库也采用了这样的方法,***因此在单page中数据过多时引入了多page的概念,而更多page的时候引入的目录的概念;***那么当前,在一个Page内部,我们引入了目录。

比如,我们要查找id=4记录,之前必须线性遍历4次,才能拿到结果。++现在直接通过目录项2[3],直接进行定位新的起始位置,提高了效率++。在单表数据不断被插入的情况下, MySQL 会在容量不足的时候,自动开辟新的Page来保存新的数据,然后通过指针的方式,将所有的Page组织起来。使用一个目录项来指向某一页,而这个目录项存放的就是将要指向的页中存放的最小数据的键值

"空间换时间"

5.4.2 页目录和页内目录的区别

和页内目录不同的地方在于,这种目录管理的级别是页,而页内目录管理的级别是行。

其中,每个

目录项的构成是:键值+指针

5.5 目录页很多情况

其实目录页的本质也是页,普通页中存的数据是用户数据,而目录页中存的数据是普通页的地址。可是,我们每次检索数据的时候,该从哪里开始呢?虽然顶层的目录页少了,但是还要遍历啊?不用担心,可以再加目录页;

我们发现这就是传说中的B+树啊!没错,至此,我们已经给我们的表user构建完了主键索引。随便找一个id=?我们发现,现在查找的Page数一定减少了,淘汰率变高了,也就意味着IO次数减少了,那么效率也就提高了。

(B+树结构)

5.4 索引查找的本质总结

①Page分为目录页和数据页。目录页只放各个下级Page的最小键值

②查找的时候,自定向下找,只需要加载部分目录页到内存,即可完成算法的整个查找过程,大大减少了IO次数;

非叶子结点不存数据,则可以存储更多的目录项,也就可以管理更多的page,这样这棵树一定是矮胖的,所以途径的变短,所以IO次数减少,也就提高了效率;所以这棵树就叫做innode db索引结构,所以我们mysql的增删查改就是在这棵树上进行的;

这棵树是被构建在哪里的呢?

答案是在我们mysql的buffer Pool中,一个表一个B+树

6.其他的数据结构为什么不可以

很多树都会最糟糕的时候都会退化成线性结构,而B树中会在路上的结点也存储数据,而彼此的叶子结点没有链式相连;

7.聚簇索引 VS 非聚簇索引

7.1MyISAM的相关特点

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

MyISAM的存储特点:

7.3MyISAM 和 InnoDB的区别

InnoDB 的非主键索引中叶子节点并没有数据,而只有对应记录的key(主键)值。

所以通过辅助(普通)索引,找到目标记录,需要两遍索引:首先检索辅助索引获得主键,然后

主键到主索引中检索获得记录。这种过程,就叫做回表查询;为何 InnoDB 针对这种辅助(普通)索引的场景,不给叶子节点也附上数据呢?原因就是太浪费空间

7.4 在mysql中看inno db 和 myisam的区别:

① innodb

首先先在mysql中建一张表,搜索引擎使用innoDB ;

然后再linux中看对应的信息

② myisam

7.5 myisam和innodb在实际开发的选择

MyISAM 是老古董,除非你是维护老系统或者有特殊需求(比如纯日志),否则不用考虑它。

相关推荐
数据知道1 小时前
MongoDB灾难恢复计划:RTO/RPO目标下的应急响应完整方案
数据库·mongodb·wpf
匀泪1 小时前
云原生(Redis配置)
数据库·redis·缓存
shuair1 小时前
redis执行lua脚本
数据库·redis·lua
楼兰胡杨2 小时前
MySQL不推荐使用UUID等字符串做主键
mysql·面试题
Andytoms2 小时前
错误信息:请在mysql配置文件修sql-mode或sql_mode为NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
数据库·sql·mysql
ChaITSimpleLove2 小时前
PostgreSQL(简称 pgsql)数据库的启动与关闭
数据库·postgresql·start·stop·reload·restart
数据知道2 小时前
MongoDB的Kerberos认证:详细讲述大型企业环境安全集成的实用技术
数据库·安全·mongodb
仙俊红2 小时前
项目上线后,发现一个接口比较慢,应该如何排查
数据库