sqlserver select 数值精度_SQL Server读懂语句运行 (二) SET STATISTICS IO ON

对于语句的运行,除了执行计划本身,还有一些其他因素要考虑,例如语句的编译时间、执行时间、做了多少次磁盘读等。

这些信息对分析问题很有价值。

1 SET STATISTICS TIME ON
2 SET STATISTICS IO ON
3 SET STATISTICS PROFILE ON

今天,看一下 SET STATISTICS IO ON的作用

先说结论,逻辑读取LOB逻辑读取是2个重要数值,在性能调优时,我们要重点围观。通常创建合适的索引或重写查询可以帮助我们彻底降低这2个值:

USE StatisticsDB
GO
SELECT * INTO SalesOrderDetail FROM AdventureWorks2008R2.Sales.SalesOrderDetail
GO
SET STATISTICS IO ON
DBCC dropcleanbuffers
DBCC freeproccache
GO
SELECT * FROM SalesOrderDetail
GO
SELECT * FROM SalesOrderDetail

17b5222cc72055cf02a469418e066e4b.png

Set Statistics IO的输出信息可以在消息TAB页里找到。同样的语句我们执行了2次,第一次是在清空缓存后执行,第2次没有。

我们来看下输出信息:

扫描计数(Scan count):

根据微软在线帮助,扫描计数是在任何方向都达到叶级别后启动的查询/扫描数,目的在于检索用于构造输出的最终数据集的所有值。

  • 如果使用的索引是主键的唯一索引或聚集索引并且您仅查找一个值,则扫描计数为 0。 例如 WHERE Primary_Key_Column = <value>。
  • 当您使用对非主键列定义的非唯一的聚集索引搜索一个值时,扫描计数为 1。 这是为了针对您正在搜索的键值检查重复值。 例如 WHERE Clustered_Index_Key_Column = <value>。
  • 当 N 为通过使用索引键定位键值后,在叶级别的左侧或右侧启动的不同查找/扫描数时,则扫描计数为 N。

这个数字告诉我们优化器所选择的计划,对这个对象的重复读取次数。很多人误以为这个是对整张表的读取次数,这是完全错误的。

我们通过一个例子来理解扫描计数。

CREATE TABLE ScanCount (Id INT IDENTITY(1,1),Value CHAR(1))
INSERT INTO ScanCount (Value ) VALUES ('A') ,('B'),('C'),('D'), ('E') , ('F')
CREATE UNIQUE CLUSTERED INDEX ix_ScanCount ON ScanCount(Id)

SET STATISTICS IO ON
--Unique clustered Index used to search single value
SELECT * FROM ScanCount  WHERE Id =1
--Unique clustered Index used to search multiple value
SELECT * FROM ScanCount  WHERE Id IN(1,2,3,4,5,6)
--Unique clustered Index used to search multiple value
SELECT * FROM ScanCount  WHERE Id BETWEEN 1 AND 6

我们来看下上面3个查询语句的输出。

fc87af57c8ed2b1eb88ea2fb10313804.png

在第1个SELECT语句的输出里,扫描计数为0。这和MSDN里在线帮助“如果使用的索引是主键的唯一索引或聚集索引并且您仅查找一个值,则扫描计数为 0。”描述一致。因为它是唯一索引(聚集/非聚集索引),不需要在叶子层,进行进一步的向左或向右扫描,因为这里只有一个值来匹配。那也是在唯一索引上查找单一值,扫描计数为0的原因。扫描计数是1的话,会在非唯一索引(聚集或非聚集索引)上发生。

对于第2个SELECT语句,扫描计数是6.这是因为我们在找多个不同值。MSDN在线帮助对此有详细说明: “如果使用的索引是主键的唯一索引或非聚集索引,你在查找N个值,则扫描计数为N。”。

我们来看看执行计划里的SEEK谓语,将更清晰:

aaa3124d67c616b3433029bc6dabadef.png

即使只有一个where条件,还是会分裂成多个谓语。对于每个SEEK谓语,它会生成1个扫描数。

对于最后一个SELECT语句,扫描计数为1,因为MSDN在线帮助说了: “当 N 为通过使用索引键定位键值后,在叶级别的左侧或右侧启动的不同查找/扫描数时,则扫描计数为 N。” 在叶子节点聚集索引结构用来找到1值后,叶子层的向左扫描开始,直到找到值6。我们看下执行计划里的SEEK 谓语,将更清晰:

c6fae06ff2451cac965da37f2e514cd4.png

逻辑读取(logical Read):

从数据缓存读取的页数。数字越小,性能越好。在性能调优中这个数字非常重要。因为它不会随着执行又执行而改变,除非数据或查询语句有变动。在进行性能调优时,这个可以作为性能提升的重要参考。

从数据缓存读取的页数。页数越多,说明查询要访问的数据量就越大,内存消耗量越大,查询也就越昂贵。可以检查是否应该调整索引,减少扫描的次数,缩小扫描范围

物理读取(physical reads):

从磁盘读取的页数。这个会随着执行又执行而改变。大多数情况下,连续第2次的执行时,它的物理读取值为0(可以参考上面连续查询的物理读取数变化)。

b0fd09d6eb40e9acbbfd3a1e0ab06695.png

如果连续执行后,物理读取次数下降了,我们可以假定是服务器上内存使用配置的错误,或者服务器工作量饱和,有内存压力。你需要在服务器级别思考问题的原因。在查询调优时,这个数字不太重要,因为它一直在变,对于下降这个值,你不能对它做出太多控制。

预读 (read-ahead reads):

为进行查询而放入缓存的页数。这个值告诉我们物理页读取数,即SQL Server执行的,作为预读机制的一部分。在查询执行请求那些可能用到页之前,SQL Server把物理数据页读入缓存,用于完成接下来查询的页需要。

0891a461ee5f3df48538998b598b38b3.png

可以看到,物理读取是2次,预读是946次。这就是说,查询执行请求了2个页,并预读了946个页到数据缓存,SQL Server估计下次查询可能要用到这些页。和物理读取一样,这个值对在查询调优里并不重要。

lob 逻辑读取(lob logical reads):

从数据缓存读取的 text、ntext、image 或大值类型 (varchar(max)、nvarchar(max)、varbinary(max)) 页的数目。这个和逻辑读一样重要,我们要非常重视

lob 物理读取(lob physical reads):

从磁盘读取的 text、ntext、image 或大值类型页的数目。

lob 预读(lob read-ahead reads):

为进行查询而放入缓存的 text、ntext、image 或大值类型页的数目。

转自:

性能调优:理解Set Statistics IO输出​www.cnblogs.com
d49cc6ecae4d233e23065e09b2658fd0.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值