当我们想学习优化的时候需要了解语句的io情况我们通常要做的就是在这个语句前开启 set statistics io on 当然你也可以通过 ssms中的工具>>选项中永久打开这儿选项,开启方法如图:
然后在我们执行完语句之后 我们就可以看到这样的结果 里面我们有逻辑读、物理读、预读等概念,我们不经有些疑问这些概念是什么作用呢?
SQL SERVER数据存储的形式
这个要从sqlserver的存储机制说起,SQL SERVER存储的最小单位为页(Page).每一页大小为8k,这个具有原子性,原子性就是说不可拆分性(我记得高中物理好像是这么意思吧。。。),总之就是说,当sqlserver读取页上的数据的时候,要吗都不读,要读就把整页的数据都读走。所以以上的三种读的单位是页。
sqlserver页的大小为8k,但是一页存储的数据为:8k=8192字节-96字节(页头)-36(行偏移)=8060字节,所以每一页用于存储的实际大小为8060字节。(那么问题来了,为什么有页头,为什么有行偏量?小的目前也不知道。。。)我们继续,首先我们查看qimenlogs的表大小 这个通过ssms我们可以看到 39.625mb
我们计算一下39.625*1024*1024/8060≈5155页-其中一些非数据存储≈5072页(也就是逻辑读的次数)现在你肯定还一头雾水,这个到底是弄啥呢,不要急,马上拨开迷雾见彩虹
SQL SERVER查询语句执行的顺序
SQL Server的查询从理解各种读的步骤来看,可以理解为以下图:
(这个图为CareySon、逆心两位大神的)
sqlserver在执行第一步的时候,会同时用估算的数据去磁盘读取数据(预读),注意这两步是同时进行的,这个是sqlserver用这中方式来提高查询性能。
(注:查询计划在生成,但未交给查询执行器执行之前,SQL SERVER 并不产生‘预读(但在生成执行计划时,查询处理器需要读取各个表的定义及表上各个索引的统计信息)。
当查询计划生成后,真正交给查询执行器执行时,SQL server 才会使用另外一个线程将查询“可能需要的数据”从磁盘读取的缓冲区中(前提是数据不在缓存中),这就是预读。同时这也意味着查询执行时进行逻辑运算的线程与“预读”所使用的线程并不是相同的线程)
当执行计划生成之后,直接去缓存读取数据,当发现缺少必须的数据的时候,再去磁盘读取(物理读),最后从缓存中将数据读出来(逻辑读) (同样的问题来了:sqlserver缓存在哪里?)
另外提供一个DMV:sys.dm_db_index_physical_stats
SELECT * FROM sys.dm_db_index_physical_stats (DB_ID('test'),OBJECT_ID('qimenlogs'),NULL,NULL,'sampled')
其中 根据page_count来进行预读
注:本文学习自:http://www.cnblogs.com/CareySon/archive/2011/12/23/2299127.html
http://www.cnblogs.com/kissdodog/archive/2013/06/25/3155016.html
感谢两位大神