MySQL 的经常使用引擎

1. InnoDB

InnoDB 的存储文件有两个,后缀名分别是 .frm 和 .idb,其中 .frm 是表的定义文件,而 idb 是数据文件。node

InnoDB 中存在表锁和行锁,不过行锁是在命中索引的状况下才会起做用。算法

InnoDB 支持事务,且支持四种隔离级别(读未提交、读已提交、可重复读、串行化),默认的为可重复读;而在 Oracle 数据库中,只支持串行化级别和读已提交这两种级别,其中默认的为读已提交级别。数据库

2. Myisam

Myisam 的存储文件有三个,后缀名分别是 .frm、.MYD、MYI,其中 .frm 是表的定义文件,.MYD 是数据文件,.MYI 是索引文件。缓存

Myisam 只支持表锁,且不支持事务。Myisam 因为有单独的索引文件,在读取数据方面的性能很高 。数据结构

3. 存储结构

InnoDB 和 Myisam 都是用 B+Tree 来存储数据的。ide

MySQL 的数据、索引存储结构

1. 数据存储的原理(硬盘)

信息存储在硬盘里,硬盘是由不少的盘片组成,经过盘片表面的磁性物质来存储数据。性能

把盘片放在显微镜下放大,能够看到盘片表面是凹凸不平的,凸起的地方被磁化,表明数字 1,凹的地方没有被磁化,表明数字 0,所以硬盘能够经过二进制的形式来存储表示文字、图片等的信息。优化

硬盘有不少种,可是都是由盘片、磁头、盘片主轴、控制电机、磁头控制器、数据转换器、接口、缓存等几个部分组成。spa

全部的盘片都固定在一个旋转轴上,这个轴即盘片主轴。操作系统

全部的盘片之间是绝对平行的,在每一个盘片的盘面上都有一个磁头,磁头与盘片之间的距离比头发丝的直径还小。

全部的磁头连在一个磁头控制器上,由磁头控制器负责各个磁头的运动,磁头可沿盘片的半径方向移动,其实是斜切运动,每一个磁头同一时刻必须是同轴的,即从正上方往下看,全部磁头任什么时候候都是重叠的。

因为技术的发展,目前已经有多磁头独立技术了,在此不考虑此种状况。

盘片以每分钟数千转到上万转的速度在高速运转,这样磁头就能对盘片上的指定位置进行数据的读写操做。

因为硬盘是高精密设备,尘埃是其大敌,因此必须彻底密封。

2. 数据读写的原理

硬盘在逻辑上被划分为磁道、柱面以及扇区。

磁头靠近主轴接触的表面,即线速度最小的地方,是一个特殊的区域,它不存听任何数据,称为启停区或者着陆区,启停区外就是数据区。

在最外圈,离主轴最远的地方是 “0” 磁道,硬盘数据的存放就是从最外圈开始的。

在硬盘中还有一个叫 “0” 磁道检测器的构件,它是用来完成硬盘的初始定位。

盘面

硬盘的盘片通常用铝合金材料作基片,硬盘的每个盘片都有上下两个盘面,通常每一个盘面都会获得利用,均可以存储数据,成为有效盘面,也有极个别的硬盘盘面数为单数。

每个这样的有效盘面都有一个盘面号,按顺序从上至下从 0 开始编号。

在硬盘系统中,盘面号又叫磁头号,由于每个有效盘面都有一个对应的读写磁头,硬盘的盘片组在 2-14 片不等,一般有 2-3 个盘片。

磁道

磁盘在格式化时被划分红许多同心圆,这些同心圆轨迹叫作磁道。

磁道从外向内从 0 开始顺序编号,硬盘的每个盘面有 300-1024 个磁道,新式大容量硬盘每面的磁道数更多,信息以脉冲串的形式记录在这些轨迹中,这些同心圆不是连续记录数据,而是被划分红一段段的圆弧。

这些圆弧的角速度同样,因为径向长度不同,因此线速度也不同,外圈的线速度较内圈的线速度大,即一样的转速度下,外圈在一样时间段里,划过的圆弧长度要比内圈划过的圆弧长度大。

每段圆弧叫作一个扇区,扇区从 1 开始编号,每一个扇区中的数据做为一个单元同时读出或写入。

磁道是看不见的,只是盘面上以特殊形式磁化了的一些磁化区,在磁盘格式化时就已规划完毕。

柱面

全部盘面上的同一磁道构成一个圆柱,一般称做柱面。

每一个圆柱上的磁头由上而下从 0 开始编号,数据的读 / 写按柱面进行,即磁头读 / 写数据时首先在同一柱面内从 0 磁头开始进行操做,依次向下在同一柱面的不一样盘面即磁头上进行操做。

只有在同一柱面全部的磁头所有读 / 写完毕后磁头才转移到下一柱面(同心圆再往里的柱面),由于选取磁头只须要经过电子切换便可,而选取柱面则必须机械切换,电子切换至关快,比在机械上的磁头向邻近磁道移动快得多。

因此,数据的读 / 写按柱面进行,而不按盘面进行,也就是说,一个磁道写满数据后,就在同一柱面的下一个盘面来写,一个柱面写满后,才移到下一个扇区开始写数据,读数据也按照这种方式进行,这样就提升了硬盘的读 / 写效率。

扇区

操做系统以扇区形式将信息存储在硬盘上,每一个扇区包括 512 个字节的数据和一些其余信息,一个扇区有两个主要部分:存储数据地点的标识符和存储数据的数据段。

标识符就是扇区头标,包括组成扇区三维地址的三个数字:盘面号,柱面号,扇区号(块号)。

数据段可分为数据和保护数据的纠错码(ECC)。在初始准备期间,计算机用 512 个虚拟信息字节(实际数据的存放地)和与这些虚拟信息字节相应的 ECC 数字填入这个部分。

3. 访盘请求完成过程

1)肯定磁盘地址(柱面号,磁头号,扇区号),内存地址(源 / 目):

当须要从磁盘读取数据的时候,系统会将数据的逻辑地址传递个磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即肯定要读的数据在哪一个磁道,哪一个扇区。

2)为了读取这个扇区的数据,须要将磁头放到这个扇区上方,为了实现这一点:

 

  • A. 首先必须找到柱面,即磁头须要移动对准相应磁道,这个过程叫作寻道,所耗费时间叫作寻道时间。
  • B. 而后目标扇区旋转到磁头下,即磁盘旋转将目标扇区旋转到磁头下,这个过程耗费的时间叫作旋转时间。

 

3)即一次访盘请求(读 / 写)完成过程由三个动做组成:

 

  • A. 寻道(时间):磁头移动定位到指定磁道。
  • B. 旋转延迟(时间):等待指定扇区从磁头下旋转通过。
  • C. 数据传输(时间):数据在磁盘与内存之间的实际传输。

 

4. 磁盘的读写原理

系统将文件存储到磁盘上时,按柱面、磁头、扇区的方式进行,即最早是第 1 磁道的第一磁头下的全部扇区,而后是同一柱面的下一个磁头……

一个柱面存储满后就推动到下一个柱面,直到把文件内容所有写入磁盘。

系统也以相同的顺序读出数据,读出数据时经过告诉磁盘控制器要读出扇区所在柱面号、磁头号和扇区号(物理地址的三个组成部分)进行。

5. 减小 I/O 的预读原理

因为存储介质的特性,磁盘自己存取就比主存慢不少,再加上机械运动耗费的时间,磁盘的存取速度每每是主存的几百分之一。

所以,为了提升效率,要尽可能减小磁盘的 I/O。

磁盘每每不是严格地按需读取,而是每次都会预读,即便只须要一个字节,磁盘也会从这个位置开始,顺序向后读取必定长度的数据放入内存。

这样作的理论依据是计算机科学中著名的局部性原理:

 

  1. 当一个数据被用到时,其附近的数据通常来讲也会被立刻使用。
  2. 程序运行期间所须要的数据一般比较集中。
  3. 因为磁盘顺序读取的效率很高(不须要寻道时间,只须要不多的旋转时间),所以对于具备局部性的程序来讲,预读能够提升 I/O 效率。

 

预读的长度通常为页(Page)的整数倍。页是计算机管理存储器的逻辑块,硬件及操做系统每每将主存和磁盘存储分割为连续的大小相等的块。

每一个存储块称为一页(在许多操做系统中,页的大小一般为 4k),主存和磁盘以页为单位交换数据,当程序要读取的数据不在主存中时,会触发一个缺页异常。

此时系统会向磁盘发出读盘信息,磁盘会找到数据的起始位置并向后连续读取一页或几页的数据载入内存中,而后异常返回,程序继续运行。

6. MySQL 的索引

索引是一种用来实现 MySQL 高效获取数据的数据结构。

咱们一般所说的在某个字段上建索引,意思就是让 MySQL 对该字段以索引这种数据结构来存储,而后查找的时候就有对应的查找算法。

建索引的根本目的是为了查找的优化,特别是当数据很庞大的时候,通常的查找算法有顺序查找、折半查找、快速查找等。

可是每种查找算法都只能应用于特定的数据结构之上,例如顺序查找依赖于顺序结构,折半查找经过二叉查找树或红黑树实现二分搜索。所以在数据以外,数据库系统还维护着知足特定查找算法的数据结构。

这些数据结构以某种方式引用数据,这样就能够在这些数据结构上实现高级查找算法,这种数据结构就是索引。

7. MySQL 的 B+Tree

目前大多数数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 做为索引结构。

B+ 树索引是 B+ 树在数据库中的一种实现,是最多见也是数据库中使用最为频繁的一种索引。B+ 树中的 B 表明平衡,而不是二叉。

由于 B+ 树是从最先的平衡二叉树演化而来的。B+ 树是由二叉查找树、平衡二叉树(AVLTree)和平衡多路查找树(B-Tree)逐步优化而来。

二叉查找树:左子树的键值小于根的键值,右子树的键值大于根的键值。

AVL 树:平衡二叉树(AVL 树)在符合二叉查找树的条件下,还知足任何节点的两个子树的高度最大差为 1。

平衡多路查找树(B-Tree):为磁盘等外存储设备设计的一种平衡查找树。

系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一磁盘块中的数据会被一次性读取出来,而不是按需读取。

InnoDB 存储引擎使用页做为数据读取单位,页是其磁盘管理的最小单位,默认 page 大小是 16k。

系统的一个磁盘块的存储空间每每没有这么大,所以 InnoDB 每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小 16KB。

InnDB 在把磁盘数据读入到磁盘时会以页为基本单位,在查询数据时若是一个页中的每条数据都能助于定位数据记录的位置,这将会减小磁盘 I/O 的次数,提升查询效率。

B-Tree 结构的数据可让系统高效的找到数据所在的磁盘块。

为了描述 B-Tree,首先定义一条数据记录为一个二元组 [key, data],key 为记录的键值,对于不一样数据记录,key 是互不相同的;data 为数据记录除 key 外的数据。

那么 B-Tree 是知足下列条件的数据结构:

  1. d 为大于 1 的一个正整数,称为 B-Tree 的度。
  2. h 为一个正整数,称为 B-Tree 的高度。
  3. 每一个非叶子节点由 n-1 个 key 和 n 个指针组成,其中 d<=n<=2d。
  4. 每一个叶子节点最少包含一个 key 和两个指针,最多包含 2d-1 个 key 和 2d 个指针,叶节点的指针均为 null 。
  5. 全部叶节点具备相同的深度,等于树高 h。
  6. key 和指针互相间隔,节点两端是指针。
  7. 一个节点中的 key 从左到右非递减排列。
  8. 全部节点组成树结构。
  9. 每一个指针要么为 null,要么指向另一个节点。
  10. 若是某个指针在节点 node 最左边且不为 null,则其指向节点的全部 key 小于 v(key1),其中 v(key1) 为 node 的第一个 key 的值。
  11. 若是某个指针在节点 node 最右边且不为 null,则其指向节点的全部 key 大于 v(keym),其中 v(keym) 为 node 的最后一个 key 的值。
  12. 若是某个指针在节点 node 的左右相邻 key 分别是 keyi 和 keyi+1 且不为 null,则其指向节点的全部 key 小于 v(keyi+1) 且大于 v(keyi)。

B-Tree 中的每一个节点根据实际状况能够包含大量的关键字信息和分支,例:

每一个节点占用一个盘块的磁盘空间,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。

两个关键词划分红的三个范围域对应三个指针指向的子树的数据的范围域。

以根节点为例,关键字为 17 和 35,P1 指针指向的子树的数据范围为小于 17,P2 指针指向的子树的数据范围为 17~35,P3 指针指向的子树的数据范围为大于 35。

模拟查找关键字 29 的过程:

  1. 根据根节点找到磁盘块 1,读入内存。【磁盘 I/O 操做第 1 次】
  2. 比较关键字 29 在区间(17,35),找到磁盘块 1 的指针 P2。
  3. 根据 P2 指针找到磁盘块 3,读入内存。【磁盘 I/O 操做第 2 次】
  4. 比较关键字 29 在区间(26,30),找到磁盘块 3 的指针 P2。
  5. 根据 P2 指针找到磁盘块 8,读入内存。【磁盘 I/O 操做第 3 次】
  6. 在磁盘块 8 中的关键字列表中找到关键字 29。

MySQL 的 InnoDB 存储引擎在设计时是将根节点常驻内存的,所以力求达到树的深度不超过 3,也就是说 I/O 不须要超过 3 次。

分析上面过程,发现须要 3 次磁盘 I/O 操做,和 3 次内存查找操做。因为内存中的关键字是一个有序表结构,能够利用二分法查找提升效率。

而 3 次磁盘 I/O 操做是影响整个 B-Tree 查找效率的决定因素。

B-Tree 相对于 AVLTree 缩减了节点个数,使每次磁盘 I/O 取到内存的数据都发挥了做用,从而提升了查询效率。

B+Tree 是在 B-Tree 基础上的一种优化,使其更适合实现外存储索引结构,InnoDB 存储引擎就是用 B+Tree 实现其索引结构。

在 B-Tree 中,每一个节点中有 key,也有 data,而每个页的存储空间是有限的,若是 data 数据较大时将会致使每一个节点(即一个页)能存储的 key 的数量很小。

当存储的数据量很大时一样会致使 B-Tree 的深度较大,增大查询时的磁盘 I/O 次数,进而影响查询效率。

在 B+Tree 中,全部数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储 key 值信息,这样能够大大加大每一个节点存储的 key 值数量,下降 B+Tree 的高度。

B+Tree 在 B-Tree 的基础上有两点变化:

  1. 数据是存在叶子节点中的;
  2. 数据节点之间是有指针指向的

因为 B+Tree 的非叶子节点只存储键值信息,假设每一个磁盘块能存储 4 个键值及指针信息,则变成 B+Tree 后其结构以下图所示:

一般在 B+Tree 上有两个头指针,一个指向根节点,另外一个指向关键字最小的叶子节点,并且全部叶子节点(即数据节点)之间是一种链式环结构。

所以能够对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另外一种是从根节点开始,进行随机查找。

8. Myisam 中的 B+Tree

Myisam 引擎也是采用的 B+Tree 结构来做为索引结构。

因为 Myisam 中的索引和数据分别存放在不一样的文件,因此在索引树中的叶子节点中存的数据是该索引对应的数据记录的地址,因为数据与索引不在一块儿,因此 Myisam 是非聚簇索引。

 

9. InnoDB 中的 B+Tree

InnoDB 是以 ID 为索引的数据存储。

采用 InnoDB 引擎的数据存储文件有两个,一个定义文件,一个是数据文件。

InnoDB 经过 B+Tree 结构对 ID 建索引,而后在叶子节点中存储记录。

 

若建索引的字段不是主键 ID,则对该字段建索引,而后在叶子节点中存储的是该记录的主键,而后经过主键索引找到对应的记录。

相关文章
相关标签/搜索