我們知道統計信息會直接決定關系引擎產生何種執行計划,這篇文章通過演示2個例子像大家展示
1、統計信息對連接方式的影響
2、統計信息對單表數據獲取方式的影響
以下內容是我曾經做過的一次培訓內容,測試環境是SQLServer 2008 R2。如果你還不明白什么是統計信息,請點這里
先來看下統計信息對連接方式的影響,
首先創建一個測試DB,並將“自動創建統計信息”和“自動更新統計信息”設置成OFF,然后運行一下代碼創建相關表和寫入記錄
CREATE TABLE CHECK2_T1 ( ID INT, C1 CHAR(800) ) CREATE TABLE CHECK2_T2 ( ID INT, C1 CHAR(8000) ) --向兩個表中插入數據 BEGIN TRAN DECLARE @I INT SET @I=1 WHILE @I<=100000 BEGIN INSERT INTO CHECK2_T1 SELECT @I,'C1' SET @I=@I+1 END COMMIT TRAN BEGIN TRAN DECLARE @I INT SET @I=1 WHILE @I<=500000 BEGIN INSERT INTO CHECK2_T2 SELECT @I,'C2' SET @I=@I+1 END COMMIT TRAN
然后執行以下兩句sql,②中的sql用了表提示HASH,目的是模擬有統計信息的情況,稍后會演示有統計信息的情況
下面兩句sql根據查詢條件可知結果集為0行,我們看下他們的執行計划。
①SELECT A.* FROM CHECK2_T1 A INNER JOIN CHECK2_T2 B ON A.ID=B.ID WHERE A.C1='C3' ②SELECT A.* FROM CHECK2_T1 A INNER HASH JOIN CHECK2_T2 B ON A.ID=B.ID WHERE A.C1='C3'
執行計划如下:
對比以上兩個執行計划,發現①中的兩表連接用的是“合並連接”,CHECK2_T2這張被全表掃描,現在你應該明白我們將CHECK2_T2表模擬成一條記錄一個8K頁的意義,實際上單獨這張表已經占用了50W個page,大約4G磁盤空間,對它進行表掃描自然會慢。
看了①的執行計划,我們知道優化的話就是要去掉這個“合並連接”,改成“嵌套循環”或者“哈希連接”都能達到我們的效果,於是就有了②sql中我們通過連接提示強制計划走“哈希匹配”,我們看到②的sql是瞬時出來的,達到了我們的目的,當然我們也可以將"HASH"提示改成“LOOP”提示,讓查詢走“嵌套循環”的方式,其效果也是瞬時出來的,查詢計划如下
現在我們看到通過添加連接提示達到了想要的執行計划,但這並不是我們建議的,我們看到執行計划中表掃描的圖標中有個黃色的三角嘆號,鼠標移上去它提示我們該表上缺少XX統計信息,比如CHECK2_T1上提示我們C1列上缺少統計信息,這個直接導致了sqlserver產生了一個不好的執行計划,我們手動在CHECK2_T1表的C1列上創建統計信息WX_C1,
創建完成后再次執行①的sql,發現默認的執行計划開始走“哈希匹配”,也是瞬時完成查詢,執行計划如下
目前為止向大家展示了統計信息對執行計划中表連接的影響,下一篇文章會演示統計信息對單表查詢計划的影響。
需要說明的是,實際上我也無法說清楚的解析統計信息是如何導致不同的的查詢計划,這是sqlserver引擎內部的東西,資料也相對較少,但是大家應該明白統計信息的重要性,就像微軟官方文檔所說的,過期的統計信息可能嚴重影響系統性能。最好保持默認的數據庫“自動創建統計和自動更新統計信息”打開狀態,除非你有足夠的理由不采用自動創建和自動更新統計信息的功能。