在SQLSERVER查询分析器中,当咱们用Set Statistics on 语句来统计SQL语句或者存储过程I/O的时候,html
SQLSERVER会显示几个概念去词语:逻辑读取,物理读取,预读。缓存
以下:性能
(1 行受影响)
表 't2'。扫描计数 1,逻辑读取 3282 次,物理读取 44 次,预读 3282 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。spa
那么,这几个词语表明什么意思呢?咱们怎么根据这些来了解SQL语句或者存储过程的I/O过程呢?htm
预读:用于估计信息,去硬盘读取数据到缓存。blog
物理读:查询计划生成之后,若是发现缓存缺乏所须要的数据,让缓存再次去读硬盘数据。若是内存里没有缓存数据或者执行计划(若是SQL语句发生了改变,内存
那么执行计划将不能重用,须要从新生成新的执行计划),那么SQLSERVER就要去硬盘读取这些数据,这个时候就是物理读取,咱们你们都知道,硬盘速度select
与内存速度根本不在一个数量级上,因此物理读是比较慢的。并行
逻辑读:SQLSERVER去内存里的缓存取数据或者执行计划,因此逻辑读是比较快的。im
SQLSERVER存储的最小单位是页,每一页大小为8K,即8*1024=8192字节,SQLSERVER对页的读取是原子性的,即要么读完一页,要么彻底不读。即便
仅仅要得到一条数据,也要读完该页,而页之间的数据组织结构为B树结构。因此SQLSERVER对于逻辑读,物理读,预读的单位是页。
先来看一个查询:
DBCC DROPCLEANBUFFERS --清空缓存
SET STATISTICS IO ON --开启IO统计
SELECT * FROM SAMPLE --查询
显示消息以下:
(147517 行受影响)
表'SAMPLE'。扫描计数 1,逻辑读取2237次,物理读取6次,预读2226次,lob读取0次
上表的大小事17.406M。
每一页存储的数据是8K=8192字节-96字节(页头)-36字节(行偏移)=8060字节。
17.406*1024*1024/8060约等于2264.
另外表中还有一些非数据占用的空间,所以上式的结果约等于逻辑读次数。
基本上,逻辑读,物理读,预读都等因而扫描了多少个页。
SQLSERVER的查询从理解各类读的步骤来看,能够理解为下图
经过上图来解释下各类读的方式:
SQLSERVER执行一个查询语句的时候,SQLSERVER会执行第一个步骤,即生成查询计划,同时用估计的数据去磁盘读取数据(预读)
,这两个都是第一步,是并行的。SQLSERVER经过这种方式来提升查询性能。
当查询计划生成好之后,开始去缓存读取数据,当发现缓存缺乏所须要的数据的时候,让缓存再次去硬盘读取数据(物理读),而后从缓存
中取出全部数据(逻辑读)。
估计的页数能够经过DMV来看到
select pagecount from sys.dm_db_index_physical_stats
(DB_ID('TESTDATACENTER'),OBJECT_ID('SAMPLE'),null,null,'sampled')
显示结果以下:
SQLSERVER就是根据这个数值进行预读的。
若是咱们此时再执行上面的查询语句
select * from sample --查询
看到消息以下:
(147517 行受影响)
表'SAMPLE'。扫描计数1,逻辑读取2237次,物理读取0次,预读0次,lob逻辑读取0次。
读者也许不明白了,为何此次所有都是逻辑读取呢?
答案是由于刚才执行过这样一个查询,执行计划与数据都在缓存当中,因此只须要从缓存中读取就能够了,
不须要再读取硬盘。
本文系本身消化并转载
地址:http://www.studyofnet.com/news/94.html。