性能调优:理解Set Statistics IO输出
性能調(diào)優(yōu)是DBA的重要工作之一。很多人會(huì)帶著各種性能上的問(wèn)題來(lái)問(wèn)我們。我們需要通過(guò)SQL Server知識(shí)來(lái)處理這些問(wèn)題。經(jīng)常被問(wèn)到的一個(gè)問(wèn)題是:早上這個(gè)存儲(chǔ)過(guò)程運(yùn)行時(shí)間還是可以的,但到了晚上就很慢很慢。對(duì)此,我們可以笑著回答:這個(gè)存儲(chǔ)過(guò)程運(yùn)行多次后,已經(jīng)累趴了,所以很慢。
存儲(chǔ)過(guò)程或語(yǔ)句運(yùn)行時(shí)間取決于服務(wù)器的工作量。如果在晚上,服務(wù)器負(fù)擔(dān)很重的話,你的存儲(chǔ)過(guò)程可能需要更多的時(shí)間來(lái)運(yùn)行,因?yàn)樗诘却鼵PU周期(CPU cycle)和IO完成(IO completion)。為了獲得一致的響應(yīng)時(shí)間,我們需要減少執(zhí)行完成的資源需求,那就是所謂的性能調(diào)優(yōu)。
IO和CPU是完成執(zhí)行的主要資源使用對(duì)象。更少的資源使用,更穩(wěn)定的性能表現(xiàn)。這篇文章我們來(lái)理解下性能調(diào)優(yōu)中DBCC STATISTCS IO所扮演的角色。
默認(rèn)情況下SET STATISTCS IO是停用的,我們可以通過(guò)下列語(yǔ)句在當(dāng)前會(huì)話級(jí)別打開(kāi)。
1 SET STATISTICS IO ON這個(gè)語(yǔ)句可以幫助我們獲得在語(yǔ)句執(zhí)行時(shí),所發(fā)生IO數(shù)(頁(yè)讀/寫(xiě))。我們來(lái)看一個(gè)例子的輸出。
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頁(yè)里找到。同樣的語(yǔ)句我們執(zhí)行了2次,第一次是在清空緩存后執(zhí)行,第2次沒(méi)有。
我們來(lái)看下輸出信息:
掃描計(jì)數(shù)(Scan count):
根據(jù)微軟在線幫助,掃描計(jì)數(shù)是在任何方向都達(dá)到葉級(jí)別后啟動(dòng)的查詢/掃描數(shù),目的在于檢索用于構(gòu)造輸出的最終數(shù)據(jù)集的所有值。
- 如果使用的索引是主鍵的唯一索引或聚集索引并且您僅查找一個(gè)值,則掃描計(jì)數(shù)為 0。 例如 WHERE Primary_Key_Column = <value>。
-
當(dāng)您使用對(duì)非主鍵列定義的非唯一的聚集索引搜索一個(gè)值時(shí),掃描計(jì)數(shù)為 1。 這是為了針對(duì)您正在搜索的鍵值檢查重復(fù)值。 例如 WHERE Clustered_Index_Key_Column = <value>。
-
當(dāng) N 為通過(guò)使用索引鍵定位鍵值后,在葉級(jí)別的左側(cè)或右側(cè)啟動(dòng)的不同查找/掃描數(shù)時(shí),則掃描計(jì)數(shù)為 N。
這個(gè)數(shù)字告訴我們優(yōu)化器所選擇的計(jì)劃,對(duì)這個(gè)對(duì)象的重復(fù)讀取次數(shù)。很多人誤以為這個(gè)是對(duì)整張表的讀取次數(shù),這是完全錯(cuò)誤的。
我們通過(guò)一個(gè)例子來(lái)理解掃描計(jì)數(shù)。
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我們來(lái)看下上面3個(gè)查詢語(yǔ)句的輸出。
在第1個(gè)SELECT語(yǔ)句的輸出里,掃描計(jì)數(shù)為0。這和MSDN里在線幫助“如果使用的索引是主鍵的唯一索引或聚集索引并且您僅查找一個(gè)值,則掃描計(jì)數(shù)為 0。”描述一致。因?yàn)樗俏ㄒ凰饕?#xff08;聚集/非聚集索引),不需要在葉子層,進(jìn)行進(jìn)一步的向左或向右掃描,因?yàn)檫@里只有一個(gè)值來(lái)匹配。那也是在唯一索引上查找單一值,掃描計(jì)數(shù)為0的原因。掃描計(jì)數(shù)是1的話,會(huì)在非唯一索引(聚集或非聚集索引)上發(fā)生。
對(duì)于第2個(gè)SELECT語(yǔ)句,掃描計(jì)數(shù)是6.這是因?yàn)槲覀冊(cè)谡叶鄠€(gè)不同值。MSDN在線幫助對(duì)此有詳細(xì)說(shuō)明: “如果使用的索引是主鍵的唯一索引或非聚集索引,你在查找N個(gè)值,則掃描計(jì)數(shù)為N。”。
我們來(lái)看看執(zhí)行計(jì)劃里的SEEK謂語(yǔ),將更清晰:
即使只有一個(gè)where條件,還是會(huì)分裂成多個(gè)謂語(yǔ)。對(duì)于每個(gè)SEEK謂語(yǔ),它會(huì)生成1個(gè)掃描數(shù)。
對(duì)于最后一個(gè)SELECT語(yǔ)句,掃描計(jì)數(shù)為1,因?yàn)镸SDN在線幫助說(shuō)了: “當(dāng) N 為通過(guò)使用索引鍵定位鍵值后,在葉級(jí)別的左側(cè)或右側(cè)啟動(dòng)的不同查找/掃描數(shù)時(shí),則掃描計(jì)數(shù)為 N。” 在葉子節(jié)點(diǎn)聚集索引結(jié)構(gòu)用來(lái)找到1值后,葉子層的向左掃描開(kāi)始,直到找到值6。我們看下執(zhí)行計(jì)劃里的SEEK 謂語(yǔ),將更清晰:
邏輯讀取(logical Read):
從數(shù)據(jù)緩存讀取的頁(yè)數(shù)。數(shù)字越小,性能越好。在性能調(diào)優(yōu)中這個(gè)數(shù)字非常重要。因?yàn)樗粫?huì)隨著執(zhí)行又執(zhí)行而改變,除非數(shù)據(jù)或查詢語(yǔ)句有變動(dòng)。在進(jìn)行性能調(diào)優(yōu)時(shí),這個(gè)可以作為性能提升的重要參考。
物理讀取(physical reads):
從磁盤(pán)讀取的頁(yè)數(shù)。這個(gè)會(huì)隨著執(zhí)行又執(zhí)行而改變。大多數(shù)情況下,連續(xù)第2次的執(zhí)行時(shí),它的物理讀取值為0(可以參考上面連續(xù)查詢的物理讀取數(shù)變化)。
如果連續(xù)執(zhí)行后,物理讀取次數(shù)下降了,我們可以假定是服務(wù)器上內(nèi)存使用配置的錯(cuò)誤,或者服務(wù)器工作量飽和,有內(nèi)存壓力。你需要在服務(wù)器級(jí)別思考問(wèn)題的原因。在查詢調(diào)優(yōu)時(shí),這個(gè)數(shù)字不太重要,因?yàn)樗恢痹谧?#xff0c;對(duì)于下降這個(gè)值,你不能對(duì)它做出太多控制。
預(yù)讀 (read-ahead reads):
為進(jìn)行查詢而放入緩存的頁(yè)數(shù)。這個(gè)值告訴我們物理頁(yè)讀取數(shù),即SQL Server執(zhí)行的,作為預(yù)讀機(jī)制的一部分。在查詢執(zhí)行請(qǐng)求那些可能用到頁(yè)之前,SQL Server把物理數(shù)據(jù)頁(yè)讀入緩存,用于完成接下來(lái)查詢的頁(yè)需要。
可以看到,物理讀取是2次,預(yù)讀是946次。這就是說(shuō),查詢執(zhí)行請(qǐng)求了2個(gè)頁(yè),并預(yù)讀了946個(gè)頁(yè)到數(shù)據(jù)緩存,SQL Server估計(jì)下次查詢可能要用到這些頁(yè)。和物理讀取一樣,這個(gè)值對(duì)在查詢調(diào)優(yōu)里并不重要。
lob 邏輯讀取(lob logical reads):
從數(shù)據(jù)緩存讀取的 text、ntext、image 或大值類(lèi)型 (varchar(max)、nvarchar(max)、varbinary(max)) 頁(yè)的數(shù)目。這個(gè)和邏輯讀一樣重要,我們要非常重視。
lob 物理讀取(lob physical reads):
從磁盤(pán)讀取的 text、ntext、image 或大值類(lèi)型頁(yè)的數(shù)目。
lob 預(yù)讀(lob read-ahead reads):
為進(jìn)行查詢而放入緩存的 text、ntext、image 或大值類(lèi)型頁(yè)的數(shù)目。
總結(jié)下,邏輯讀取和LOB邏輯讀取是2個(gè)重要數(shù)值,在性能調(diào)優(yōu)時(shí),我們要重點(diǎn)圍觀。如果把這2個(gè)值調(diào)低,不在本文的討論范圍。通常創(chuàng)建合適的索引或重寫(xiě)查詢可以幫助我們徹底降低這2個(gè)值。
參考文章:
http://www.sqlservercentral.com/blogs/practicalsqldba/2013/07/16/sql-server-performance-tuning-understanding-dbcc-statistics-io-output/
總結(jié)
以上是生活随笔為你收集整理的性能调优:理解Set Statistics IO输出的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ConcurrentHashMap之实现
- 下一篇: 2015年百度之星初赛(1) --- D