一、SET STATISTICS IO (有关TSQL语句查询所产生的磁盘活动量)

--显示有关由Transact-SQL 语句生成的磁盘活动量的信息

SET STATISTICS IO ON

--关闭有关由Transact-SQL 语句生成的磁盘活动量的信息

SET STATISTICS IO OFF

显示的信息如下:

(SQL语句为:select * from note500)

mysql的物理逻辑 mysql逻辑读与物理读_SQL

其中:

   

   

   

   

   【查询优化】MSSQL查询执行流程))

   

   

   

二、SET STATISTICS TIME 

mysql的物理逻辑 mysql逻辑读与物理读_缓存_02


  上面显示的信息表明,执行这次查询使用了多少CPU运行时间和运行查询使用了多少时间。CPU运行时间是对运行查询所需要的CPU资源的一种相对稳定的测量方法,与CPU的忙闲程度没有关系。但是,每次运行查询时这一数字也会有所不同,只是变化的范围没有总时间变化大。总时间是对查询执行所需要的时间(不计算阻塞或读数据的时间),由于服务器上的负载是在不断变化的,因此这一数据的变化范围有时会相当地大。

总的来说,量化地来看一个查询语句的性能可以在几个参数进行比较:

1、CPU时间。比较查询所要占用的CPU资源时间;

2、I/O。可以比较查询的循环扫描次数和逻辑读取的数据量;


查询性能指标



清空缓存的方法:

dbcc dropcleanbuffers

dbcc freeproccache


第一:一个查询首次执行时,缓存中没有相应的数据,这个时候,首先会生成一个执行计划

生成一个执行计划的方法:

选中要查询的SQL语句,然后按下CTRL+L,有下图结果

(该图的语句为:select * from note500) 

mysql的物理逻辑 mysql逻辑读与物理读_缓存_03

然后同步地,会根据计划从物理硬盘中提取相应的数据到缓冲区,这就是预读。制定执行计划和预读操作是并行进行的。

接着,如果缓冲区中没有完整的查询数据,就需要从物理硬盘中再读取出相应缺少的数据,这就是物理读

最后才是读取缓冲区中的数据,也就是逻辑读

第二:当第二次执行这个查询的时候就会直接读取缓冲区的数据,就没有预读和物理读了,因为缓冲区中已经有了相应的查询结果数据。


下面是查询的结果消息:


(5000000 行受影响)
表 'note500'。扫描计数 1,逻辑读取 33769 次,物理读取 0 次,预读 33768 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

 

 

SQL SERVER数据存储的形式


 

      在谈到几种不同的读取方式之前,首先要理解SQL SERVER数据存储的方式.SQL SERVER存储的最小单位为页(Page).每一页大小为8k,SQL SERVER对于页的读取是原子性,要么读完一页,要么完全不读,不会有中间状态。而页之间的数据组织结构为B树(请参考我之前的博文).所以SQL SERVER对于逻辑读,预读,和物理读的单位是页.

     

mysql的物理逻辑 mysql逻辑读与物理读_缓存_04

      SQL SERVER一页的总大小为:8K

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

      所以每一页用于存储的实际大小为8060字节.

      比如上面AdventureWorks中的Person.Address表,通过SSMS看到这个表的数据空间为:

     

mysql的物理逻辑 mysql逻辑读与物理读_缓存_05

      我们可以通过公式大概推算出占用了多少页:2.250*1024*1024/8060(每页的数据容量)≈293 - 表中非数据占用的空间≈290(上图中的逻辑读取数)

 

SQL SERVER查询语句执行的顺序


 

      SQL SERVER查询执行的步骤如果从微观来看,那将会非常多。这里为了讲述逻辑读等概念,我从比较高的抽象层次来看:

     

mysql的物理逻辑 mysql逻辑读与物理读_SQL_06

      图有些粗糙。

      下面我解释一下图。当遇到一个查询语句时,SQL SERVER会走第一步,分别为生成执行计划(占用CPU和内存资源),同步的用估计的数据去磁盘中取得需要取的数据(占用IO资源,这就是预读),注意,两个第一步是并行的,SQL SERVER通过这种方式来提高查询性能.

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

      最后从缓存中取出所有数据(逻辑读)。

      下面我再通过一个简单的例子说明一下:

     

mysql的物理逻辑 mysql逻辑读与物理读_mysql的物理逻辑_07

      这个估计的页数数据可以通过这个DMV看到:

 

   

mysql的物理逻辑 mysql逻辑读与物理读_mysql的物理逻辑_08

 

    当我们第一次查询完成后,再次进行查询时,所有请求的数据这时已经在缓存中,SQL SERVER这时只要对缓存进行读取就行了,也就是只用进行逻辑读:

   

mysql的物理逻辑 mysql逻辑读与物理读_SQL_09