据我所知,当表具有聚簇索引时,在针对某些数据对表进行范围扫描时会发生这种情况:
先找出较低的范围,追踪到它所在的叶子节点,然后通过下一页指针逐页遍历叶子级别只要该页中的最大值小于范围扫描的较大值即可健康)状况。
一旦到达最后一行超过该页面的页面,该过程就会停止,在该页面内进行二进制搜索以找出该记录,并返回到目前为止找到的所有记录。
如果页面不在内存中,逐页调出可能是昂贵的 I/O 操作,因此为了缓解这种情况,预读扫描由父页面在上一级完成,这样当进程前进到一个叶级页面来验证它,它已经被父级页面之一带到内存中。
我正在观看一些 SQL Server 教程视频,其中说如果在叶级别存在逻辑碎片,那么物理页面顺序与逻辑页面顺序不一致,预读扫描失败并且数据库被强制执行检索所有页面的完整 I/O 操作。
有人能告诉我为什么吗?为什么物理顺序很重要?整个遍历不就是通过叶级页面的下一页指针逻辑遍历完成的吗?
逻辑碎片对预读扫描到底有什么影响?
请注意,我是根据我掌握的最佳信息推测为什么做出这些决定的。
据我所知,这是由于使用特定 API 优化了 IO,在本例中称为ReadFileScatter。
ReadFileScatter 需要起始偏移量和从该点读取的字节数。一旦读取,磁盘上连续的字节数就会传输到非连续的内存位置(也称为缓冲区)。
因为预读,根据版本和版本,可以读取不同数量的数据,它最终成为一个大的 IO 而不是一堆小的 IO,这使得整个存储系统的吞吐量更高,尽管是以延迟为代价的。
/纯推测开始/
请记住,在做出这些 API 和选择时,旋转介质(又名旋转生锈)是主要的存储来源,SSD 并不存在。因此,让所有项目在磁盘上连续意味着我们不必在读取之间重新定位磁头,这使得整体单个连续读取比许多较小的不连续读取更快。
参考资料和进一步阅读:
第一个参考资料包括一张您可能会觉得有用的图表: