局部性原理与磁盘预读由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘 I/O。为了达到这个目的,磁盘往往不是严格按需读?。??敲看味蓟嵩ざ粒?即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存 。这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时 , 其附近的数据也通常会马上被使用 。程序运行期间所需要的数据通常比较集中 。由于磁盘顺序读取的效率很高(不需要寻道时间 , 只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高 I/O 效率 。预读的长度一般为页 ( page ) 的整倍数 。页是计算机管理存储器的逻辑块 , 硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页 (在许多操作系统中,页得大小通常为 4k ) , 主存和磁盘以页为单位交换数据 。当程序要读取的数据不在主存中时,会触发一个缺页异常 , 此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行 。
B-/+Tree 索引的性能分析到这里终于可以分析 B-/+Tree 索引的性能了 。上面说过一般使用磁盘 I/O 次数评价索引结构的优劣 。先从 B-Tree 分析,根据 B-Tree 的定义 , 可知检索一次最多需要访问 h 个节点 。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次 I/O 就可以完全载入 。为了达到这个目的,在实际实现 B-Tree 还需要使用如下技巧:每次新建节点时,直接申请一个页的空间 , 这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的 , 就实现了一个 node 只需一次 I/O。B-Tree 中一次检索最多需要 h-1 次 I/O(根节点常驻内存),渐进复杂度为 O(h) = O(log_dN)。一般实际应用中,出度d是非常大的数字,通常超过 100,因此 h 非常?。ㄍǔ2怀??3 ) 。综上所述 , 用 B-Tree 作为索引结构效率是非常高的 。而红黑树这种结构,h 明显要深的多 。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为 O(h) , 效率明显比 B-Tree 差很多 。上面还说过,B+Tree 更适合外存索引,原因和内节点出度 d 有关 。从上面分析可以看到 , d 越大索引的性能越好,而出度的上限取决于节点内 key 和 data 的大?。篸_{max} = floor(pagesize / (keysize + datasize + pointsize))。floor 表示向下取整 。由于 B+Tree 内节点去掉了 data 域,因此可以拥有更大的出度,拥有更好的性能 。
MySQL 的实现在 MySQL 中,索引属于存储引擎级别的概念 , 不同存储引擎对索引的实现方式是不同的,本文主要讨论 MyISAM 和 InnoDB 两个存储引擎的索引实现方式 。
2.1 MyISAM 索引实现MyISAM 引擎使用 B+Tree 作为索引结构,叶节点的 data 域存放的是数据记录的地址 。下图是 MyISAM 索引的原理图:

文章插图
图片
这里设表一共有三列,假设我们以 Col1 为主键,则上图是一个 MyISAM 表的主索引 ( Primary key ) 示意 。可以看出 MyISAM 的索引文件仅仅保存数据记录的地址 。在 MyISAM 中,主索引和辅助索引 ( Secondary key ) 在结构上没有任何区别,只是主索引要求 key 是唯一的,而辅助索引的 key 可以重复 。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示:

文章插图
图片
同样也是一颗 B+Tree , data 域保存数据记录的地址 。因此,MyISAM 中索引检索的算法为首先按照 B+Tree 搜索算法搜索索引 , 如果指定的 Key 存在,则取出其data域的值,然后以 data 域的值为地址,读取相应数据记录 。MyISAM 的索引方式也叫做“非聚集”的,之所以这么称呼是为了与 InnoDB 的聚集索引区分 。
2.2 InnoDB 索引实现虽然 InnoDB 也使用 B+Tree 作为索引结构,但具体实现方式却与 MyISAM 截然不同 。第一个重大区别是 InnoDB 的数据文件本身就是索引文件 。从上文知道,MyISAM 索引文件和数据文件是分离的,索引文件仅保存数据记录的地址 。而在 InnoDB 中,表数据文件本身就是按 B+Tree 组织的一个索引结构,这棵树的叶节点 data 域保存了完整的数据记录 。这个索引的 key 是数据表的主键,因此 InnoDB 表数据文件本身就是主索引 。
推荐阅读
- 事实证明,躺在ICU的李嘉欣,让我们明白了什么是“现世报”!
- 为什么手机最后1%的电可以用很久?原来我们都被它骗了
- “潘金莲”王思懿戏里走不出,与武松在一起,今53岁生活如此丰富多彩!
- win10电脑开机密码忘了怎么重置密码
- 三大队:整容后的王大勇终于露面!和我们猜测的都不一样
- Ai要咋才可以用切片工具,ai多个剪切的图形如何连接一起
- 欧阳娜娜和姐妹一起接受采访,否认从小赚钱养家,妈妈才是主心骨
- 74岁王薇薇和俩女儿一起过圣诞!母女三人同穿蓝裙,比女儿还惊艳
- 和梁朝伟没娃,58岁刘嘉玲晒和干儿子康康合照感慨“一晃眼一米八”,曾称和他有前世缘分:我们好像失散很久
- 我们一起聊聊K8s定时备份MySQL并发送到指定邮箱
