歡迎來到性能調優培訓的第4個月。這個月全是關于SQL Server里的統計信息,還有它們如何幫助查詢優化器生成足夠好的執行計劃。統計信息主要是被查詢優化器用來估計查詢返回的行數。它只是個估計,沒別的。
統計信息概述SQL Server使用在統計信息對象里稱作直方圖(Histogram)的東西,它描述了對于所給列最大200步長(Steps)的數據分布情況。最大的局限性之一,對于SQL Server里的統計信息是200步長的局限性(使用過濾統計信息可以超過這個步長,這在SQL Server 2008里就引入了)。
另外的局限性是統計信息的自動更新(Auto Update)機制:對于大于500行的表,如果500+20%的列值發生改變,統計信息才會更新。這就意味著,一旦表增長,你的統計信息的自動更新頻率將越少(每次觸發自動更新需要更多的記錄修改)。
假設你有100000條記錄的表,這個情況下,如果修改了20500(20%+500)的數據,統計信息才會自動更新。如果你有1000000條記錄的表,你需要修改200500(20%+500)的數據,統計信息才會自動更新。這里用到的算法是指數的,不是線性的。在SQL Server里有2371的跟蹤標志(trace flag)也會影響這個行為。
當你的執行計劃里保航書簽查找時,這個行為就會是巨大的問題。正如你知道的,基于當前的統計信息,如果查詢的估計行數是非常少的,查詢優化器才會選擇書簽查找運算符。如果你的統計信息過期,你的執行計劃還是有效的話,SQL Server就會盲目重用緩存計劃,你的頁讀取就會暴漲。我們來看看這個問題的具體例子。
失真的統計信息(Stale Statistics)下面的腳本會創建有1500條記錄的表,在column2列有平均的數據分布。另外我們在column2列上定義非聚集索引。
1 CREATE TABLE Table1 2 ( 3 Column1 INT IDENTITY, 4 Column2 INT 5 ) 6 GO 7 8 -- Insert 1500 records into Table1 9 SELECT TOP 1500 IDENTITY(INT, 1, 1) AS n INTO #Nums10 FROM11 master.dbo.syscolumns sc112 13 INSERT INTO Table1 (Column2)14 SELECT n FROM #nums15 16 DROP TABLE #nums17 GO 18 19 CREATE NONCLUSTERED INDEX idx_Table1_Colum2 ON Table1(Column2)20 GO
當你對表進行簡單的SELECT * 查詢時,你會得到帶有書簽查找運算符的執行計劃:
1 SELECT * FROM dbo.Table1 WHERE Column2='9'
從索引查找(Non Clustered)運算符可以看到,SQL Server估計行數是1(估計行數(Estimated Number of Rows)屬性),實際上SQL Server也處理1條記錄(實際行數(Actual Number of Rows)屬性)。這就是說,我們這里用到的統計信息是準確的,查詢本身產生3個邏輯讀。
我們現在的表有1500條記錄,因此當20% + 500條記錄發生改變時,SQL Server會自動更新非聚集索引的統計信息。算一下,我們需要修改800條數據(1500 * 20% + 500)。
接下來我們對表做如下處理:我們對SQL Server做一點動作,只插入799條新記錄。但799條記錄的第2列值都是2。這就是說我們完全改變第2列的平均數據分布。統計信息會認為只有1條第2列值為2的記錄返回,但實際上卻有800條記錄返回(1條已存在的,799條新插入的):
1 SELECT TOP 799 IDENTITY(INT, 1, 1) AS n INTO #Nums2 FROM3 master.dbo.syscolumns sc14 5 INSERT INTO Table1 (Column2)6 SELECT 2 FROM #nums7 8 DROP TABLE #nums9 GO
現在我們來執行下列查詢語句,找第2列值為2的記錄,并打開執行計劃顯示和IO統計。
1 SET STATISTICS IO ON2 SELECT * FROM dbo.Table1 WHERE Column2 ='2'
SQL Server重用了有書簽查找的執行計劃。這就是說執行計劃里的書簽查找執行了1500次——一次性對所有記錄!這會耗費大量的邏輯讀——SQL Server這里報告了806個頁讀取。
從圖中可以看到,實際行數(Actual Number of Rows)現在已經遠遠超過了估計行數(Estimated Number of Rows)。
SQL Server里失真的統計信息就會帶來這樣的問題。
小結今天的性能調優培訓我給你簡單介紹了SQL Server里的統計信息。如你所見,失真的統計信息,對于緩存的,重用的執行計劃會帶來嚴重的性能問題。
我希望現在你已經能很好的理解SQL Server里的統計信息,當它們過期是,會給你的執行計劃帶來副作用。下周我會進一步討論統計信息,還有在SQL Server內部它們是怎樣的。請繼續關注。
新聞熱點
疑難解答