首页 > 代码库 > 物理读,逻辑读,预读

物理读,逻辑读,预读

在使用SET STATISTICS IO ON语句统计I/O时候,我们会看到类似下面的结果:

扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

那么它们代表什么呢?

预读:用于估计信息,去硬盘读取数据到缓存。

物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存再次去读硬盘。如果内存里没有缓存数据或执行计划(sql语句改变执行计划不能重用,需要重新计算执行计划),那么SQLSERVER就要去硬盘读取这些数据,这时候就是物理读,硬盘速度跟内存速度不在一个数量级别,所以物理读是比较慢的。

逻辑读:SQLSERVER去内存里面的缓存取数据或执行计划(执行计划可以重用),所以逻辑读是比较快的。

 SQL Server存储的最小单位是页,每一页大小为8K,SQL Server对于页的读取是原子性的,要么读完一页,要么完全不读。即使是仅仅要获得一条数据,也要读完一页。而页之间的数据组织结构为B树结构。所以SQL Server对于逻辑读、预读、物理读的单位是页。

 先来看一个查询:

  
技术分享   
技术分享   DBCC DROPCLEANBUFFERS    --清空缓存
技术分享  SET STATISTICS IO ON    --开启IO统计
技术分享  SELECT * FROM Person    --查询语句

   显示消息如下:

(147517 行受影响)
表 ‘Person‘。扫描计数 1,逻辑读取 2237 次,物理读取 6 次,预读 2226 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

  技术分享

 上表的大小是17.406M。

 每一页存储的数据是:8K=8192字节-96字节(页头)-36字节(行偏移)= 8060字节。

 17.406*1024*1024 / 8060 ≈ 2 264

 另外表中还有一些非数据占用的空间,因此上式的结果约等于逻辑读次数。

 基本上,逻辑读、物理读、预读都等于是扫描了多少个页。

 

SQL Server的查询从理解各种读的步骤来看,可以理解为以下图:

 

  技术分享

 通过上图来讲解各种读:

 当SQL Server执行一个查询语句时,SQL Serer会开始第一步,生成查询计划,同时用估计的数据去磁盘读取数据(预读),这两个第一步是并行的。SQL Server通过这种方式来提高查询性能。

 查询计划生成好了以后去缓存读取数据,当发现缓存缺少所需要的数据后让缓存再次去读硬盘(物理读)然后从缓存中取出所有数据(逻辑读)

 估计的页数可以通过DMV看到

 
技术分享
技术分享   SELECT 
技术分享  page_count
技术分享  FROM sys.dm_db_index_physical_stats
技术分享  (DB_ID(TestDataCenter),OBJECT_ID(Person),NULL,NULL,sampled)

 显示结果如下:

  技术分享

 SQL Server就是根据这个东西进行预读。

 如果此时我们再执行上面的查询语句:

  SELECT * FROM Person    --查询语句

 看到消息如下:

(147517 行受影响)
表 ‘Person‘。扫描计数 1,逻辑读取 2237 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

 为什么这次全部都是逻辑读呢。因为刚才读过一次,数据全部都已经在缓存当中了,只需要从缓存中读就可以了,不需要再读取硬盘。

物理读,逻辑读,预读