性能調優:理解Set Statistics IO輸出

性能調優是DBA的重要工做之一。不少人會帶着各類性能上的問題來問咱們。咱們須要經過SQL Server知識來處理這些問題。常常被問到的一個問題是:早上這個存儲過程運行時間仍是能夠的,但到了晚上就很慢很慢。對此,咱們能夠笑着回答:這個存儲過程運行屢次後,已經累趴了,因此很慢。sql

存儲過程或語句運行時間取決於服務器的工做量。若是在晚上,服務器負擔很重的話,你的存儲過程可能須要更多的時間來運行,由於它在等待CPU週期(CPU cycle)和IO完成(IO completion)。爲了得到一致的響應時間,咱們須要減小執行完成的資源需求,那就是所謂的性能調優。緩存

IO和CPU是完成執行的主要資源使用對象。更少的資源使用,更穩定的性能表現。這篇文章咱們來理解下性能調優中DBCC STATISTCS IO所扮演的角色。服務器

默認狀況下SET STATISTCS IO是停用的,咱們能夠經過下列語句在當前會話級別打開。ide

1 SET STATISTICS IO  ON

這個語句能夠幫助咱們得到在語句執行時,所發生IO數(頁讀/寫)。咱們來看一個例子的輸出。sqlserver

 1 USE StatisticsDB
 2 GO
 3 SELECT * INTO SalesOrderDetail FROM AdventureWorks2008R2.Sales.SalesOrderDetail 
 4 GO
 5 SET STATISTICS IO ON
 6 DBCC dropcleanbuffers
 7 DBCC freeproccache
 8 GO
 9 SELECT * FROM SalesOrderDetail 
10 GO
11 SELECT * FROM SalesOrderDetail 

 

Set Statistics IO的輸出信息能夠在消息TAB頁裏找到。一樣的語句咱們執行了2次,第一次是在清空緩存後執行,第2次沒有。性能

咱們來看下輸出信息:優化

掃描計數(Scan count):

根據微軟在線幫助,掃描計數是在任何方向都達到葉級別後啓動的查詢/掃描數,目的在於檢索用於構造輸出的最終數據集的全部值。ui

  • 若是使用的索引是主鍵的惟一索引或彙集索引而且您僅查找一個值,則掃描計數爲 0。 例如 WHERE Primary_Key_Column = <value>。
  • 當您使用對非主鍵列定義的非惟一的彙集索引搜索一個值時,掃描計數爲 1。 這是爲了針對您正在搜索的鍵值檢查重複值。 例如 WHERE Clustered_Index_Key_Column = <value>。 spa

  • 當 N 爲經過使用索引鍵定位鍵值後,在葉級別的左側或右側啓動的不一樣查找/掃描數時,則掃描計數爲 N。3d

這個數字告訴咱們優化器所選擇的計劃,對這個對象的重複讀取次數。不少人誤覺得這個是對整張表的讀取次數,這是徹底錯誤的。

咱們經過一個例子來理解掃描計數。

 1 CREATE TABLE ScanCount (Id INT IDENTITY(1,1),Value CHAR(1))
 2 INSERT INTO ScanCount (Value ) VALUES ('A') ,('B'),('C'),('D'), ('E') , ('F') 
 3 CREATE UNIQUE CLUSTERED INDEX ix_ScanCount ON ScanCount(Id)
 4 
 5 SET STATISTICS IO ON
 6 --Unique clustered Index used to search single value
 7 SELECT * FROM ScanCount  WHERE Id =1
 8 --Unique clustered Index used to search multiple value
 9 SELECT * FROM ScanCount  WHERE Id IN(1,2,3,4,5,6)
10 --Unique clustered Index used to search multiple value
11 SELECT * FROM ScanCount  WHERE Id BETWEEN 1 AND 6

咱們來看下上面3個查詢語句的輸出。

在第1個SELECT語句的輸出裏,掃描計數爲0。這和MSDN裏在線幫助「若是使用的索引是主鍵的惟一索引或彙集索引而且您僅查找一個值,則掃描計數爲 0。」描述一致。由於它是惟一索引(彙集/非彙集索引),不須要在葉子層,進行進一步的向左或向右掃描,由於這裏只有一個值來匹配。那也是在惟一索引上查找單一值,掃描計數爲0的緣由。掃描計數是1的話,會在非惟一索引(彙集或非彙集索引)上發生。

對於第2個SELECT語句,掃描計數是6.這是由於咱們在找多個不一樣值。MSDN在線幫助對此有詳細說明: 「若是使用的索引是主鍵的惟一索引或非彙集索引,你在查找N個值,則掃描計數爲N。」。

咱們來看看執行計劃裏的SEEK謂語,將更清晰:

即便只有一個where條件,仍是會分裂成多個謂語。對於每一個SEEK謂語,它會生成1個掃描數。

對於最後一個SELECT語句,掃描計數爲1,由於MSDN在線幫助說了: 「當 N 爲經過使用索引鍵定位鍵值後,在葉級別的左側或右側啓動的不一樣查找/掃描數時,則掃描計數爲 N。」 在葉子節點彙集索引結構用來找到1值後,葉子層的向左掃描開始,直到找到值6。咱們看下執行計劃裏的SEEK 謂語,將更清晰:

邏輯讀取(logical Read):

從數據緩存讀取的頁數。數字越小,性能越好。在性能調優中這個數字很是重要。由於它不會隨着執行又執行而改變,除非數據或查詢語句有變更。在進行性能調優時,這個能夠做爲性能提高的重要參考。

物理讀取(physical reads):

從磁盤讀取的頁數。這個會隨着執行又執行而改變。大多數狀況下,連續第2次的執行時,它的物理讀取值爲0(能夠參考上面連續查詢的物理讀取數變化)。

若是連續執行後,物理讀取次數降低了,咱們能夠假定是服務器上內存使用配置的錯誤,或者服務器工做量飽和,有內存壓力。你須要在服務器級別思考問題的緣由。在查詢調優時,這個數字不過重要,由於它一直在變,對於降低這個值,你不能對它作出太多控制。

預讀 (read-ahead reads):

爲進行查詢而放入緩存的頁數。這個值告訴咱們物理頁讀取數,即SQL Server執行的,做爲預讀機制的一部分。在查詢執行請求那些可能用到頁以前,SQL Server把物理數據頁讀入緩存,用於完成接下來查詢的頁須要。

能夠看到,物理讀取是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 或大值類型頁的數目。

總結下,邏輯讀取和LOB邏輯讀取是2個重要數值,在性能調優時,咱們要重點圍觀。若是把這2個值調低,不在本文的討論範圍。一般建立合適的索引或重寫查詢能夠幫助咱們完全下降這2個值。

參考文章:

http://www.sqlservercentral.com/blogs/practicalsqldba/2013/07/16/sql-server-performance-tuning-understanding-dbcc-statistics-io-output/

相關文章
相關標籤/搜索