mysql全表扫描是顺序IO吗?

我理解数据页之间并不是物理上的连续,所以不一定是顺序io,不知道我的理解对不对?

阅读 2.5k
5 个回答

全表扫描时。即将数据从磁盘上一个个读到内存中做过滤,最后返回结果。这种方式的特点是不管数据有没有用,都先读出来,磁盘读取数据总量大。所以对应磁盘的顺序访问

但是它将按照数据页的顺序读取数据,但是由于数据页之间并不是物理上连续的,因此实际上并不是完全的顺序IO操作。MySQL会尽可能地将相邻的数据页读取到内存中,以减少磁盘寻道时间和磁盘头移动时间

本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。

也可以认为是一定程度上的顺序IO。

image.png

大概这么个顺序。
页1 -> 页2 -> 页5 -> 页6 -> 页7 -> 页3 -> 页8 -> ...
最底层的叶子节点(即页5,6,7这种)默认16kb,即Linux磁盘扇区默认分区大小,每次读取就这么一块。
页内部是单链表,页与页之间是双链表。


本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。

不存在顺序 io 和随机 io

只有 顺序多一点的 io 和随机多一点的 io

mysql 的 innodb 是 B+ 树

这意味着,树的节点映射到文件中不一定连续,但是 innodb 会让节点尽可能连续,来获取硬盘的顺序 io 加速,但只是尽可能

非作者,仅借花献佛

从理论上说,不引入区的概念只使用页的概念对存储引擎的运行并没啥影响,但是我们来考虑一下边这个场景:

我们每向表中插入一条记录,本质上就是向该表的聚簇索引以及所有二级索引代表的B+树的节点中插入数据。而B+树的每一层中的页都会形成一个双向链表,如果是以页为单位来分配存储空间的话,双向链表相邻的两个页之间的物理位置可能离得非常远。我们介绍B+树索引的适用场景的时候特别提到范围查询只需要定位到最左边的记录和最右边的记录,然后沿着双向链表一直扫描就可以了,而如果链表中相邻的两个页物理位置离得非常远,就是所谓的随机I/O。再一次强调,磁盘的速度和内存的速度差了好几个数量级,随机I/O是非常慢的,所以我们应该尽量让链表中相邻的页的物理位置也相邻,这样进行范围查询的时候才可以使用所谓的顺序I/O。

所以才引入了区(extent)的概念,一个区就是在物理位置上连续的64个页。在表中数据量大的时候,为某个索引分配空间的时候就不再按照页为单位分配了,而是按照区为单位分配,甚至在表中的数据十分非常特别多的时候,可以一次性分配多个连续的区。虽然可能造成一点点空间的浪费(数据不足填充满整个区),但是从性能角度看,可以消除很多的随机I/O,功大于过嘛!

摘自《MySQL 是怎样运行的:从根儿上理解 MySQL》

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏