天天看點

SQL Server · 特性介紹 · 統計資訊

sql server查詢優化器對于執行計劃成本的評估是基于資料庫統計資訊的。是以,資料庫統計資訊直接影響到資料庫查詢效率,是資料庫系統快速響應,低延遲特性的幕後英雄,但是我們又經常忽視資料庫統計資訊的存在和維護,懷着為英雄正名和喚醒大家對幕後英雄尊重的目的寫作這篇文章。

sql server查詢優化器使用統計資訊來評估表或索引視圖的一個或多個列中值的分布,這個分布資訊提供了用于建立高品質的執行計劃的基礎(稱為基數)。更為通俗一點說,sql server的執行計劃是基于統計資訊來評估的,優化器最終會選擇最優的執行計劃來為資料庫系統提供資料存取功能。這位躲在幕後的英雄便是統計資訊。

在關系型資料庫系統(rdbms)中,統計資訊非常重要,當然mssql server也不例外,它的準确與否直接影響到執行計劃的優劣,資料庫系統查詢效率是否高效。具體表現在以下幾個方面:

查詢優化器需要借助統計資訊來判斷是否使用索引。

查詢優化器需要根據統計資訊來判斷是使用嵌套循環連接配接,合并連接配接還是哈希連接配接。

查詢優化器根據表統計資訊來找出最佳的執行順序。

前面章節我們講的都是比較枯燥的理論知識,這一小節我們來具體揭露幕後英雄的廬山真面目,它包含了哪些内容。

查詢sql server統計資訊非常簡單,隻需要使用dbcc指令傳入表名字和統計資訊名稱即可,dbcc show_statistics(‘table_name’,’statistics_name’)。我們以adventureworks2008r2資料庫下表sales.salesorderdetail中統計資訊ak_salesorderdetail_rowguid為例:

揭曉幕後英雄的真實面貌如下:

SQL Server · 特性介紹 · 統計資訊

關于統計資訊設定,有四個重要的選項。

auto create statistics:sql server是否自動建立統計資訊,預設開啟。

auto update statistics:sql server是否自動更新統計資訊,預設開啟。

auto update statistics asynchronously:sql server是否采用異步方式更新統計資訊,預設關閉。

auto create incremental statistics:sql server是否自動建立增量統計資訊,這個選項是sql server 2014以來新增選項,預設關閉。

檢驗模版資料庫model統計資訊設定,新增資料庫會以這個資料庫為模版。

結果展示如下:

SQL Server · 特性介紹 · 統計資訊

我們以adventureworks2008r2為例來觀察sql server資料庫關于統計資訊的設定。除了上面使用的檢查方法以外,我們還可以使用下面的方法。

結果顯示與model資料庫保持一緻,如下:

SQL Server · 特性介紹 · 統計資訊

當然我們也可以使用ssms gui方式檢視:right click on database => properties => options

SQL Server · 特性介紹 · 統計資訊

為了看清楚sql server統計資訊是如何影響查詢的,我們在adventureworks2008r2庫下建立一個測試表dbo.tb_teststats,并向測試表中插入10000條資料。

為了防止統計資訊在執行計劃評估階段自動建立造成對我們測試的影響,手動關閉auto create statistics選項。

接下在ssms中選擇顯示實際的實行計劃,然後執行下面的查詢語句。

從實際的執行計劃來看,實際滿足條件的記錄數沒有,即actual numbers of rows為0,而預估滿足條件的記錄數estimated numbers of rows為1000條,差異巨大,并且存在統計資訊缺失的警告。這個巨大的差異足以導緻sql server優化器對執行計劃評估不準确,進而選擇了次優的執行計劃,最終影響資料庫查詢效率。

SQL Server · 特性介紹 · 統計資訊

無統計資訊的執行計劃是從反面看統計資訊對執行計劃的影響,現在我們從正面看有統計資訊對執行計劃的影響。當我們手動建立統計資訊以後,再看看實際的執行計劃。

再次執行查詢,這裡需要特别注意,為了防止執行計劃緩存對測試結果的影響,在執行查詢語句前,我們需要清空執行計劃緩存,執行查詢語句後,我們将auto create statistics設定恢複為預設值。

最後檢視實際執行計劃,統計資訊缺失的警告消失了,預估滿足條件的行數estimated numbers of rows為1行和實際滿足條件的行數actual numbers of rows為0行,已經非常接近了。說明統計資訊的存在為優化器提供了正确的資料分布圖,給優化器選擇最優路徑帶來了積極的影響,統計資訊在此充當了sql server優化器的幕後英雄。

SQL Server · 特性介紹 · 統計資訊

既然統計資訊對查詢的效率影響如此大,那麼我們要如何來建立和維護資料庫系統的統計資訊呢?這小節會從統計資訊的自動建立,手動建立兩個大的方面來具體闡述。

還是以adventureworks2008r2庫的測試表dbo.tb_teststats為例,從上面建表的代碼來看,測試表建立了一個主鍵,主鍵是一個特殊的索引,sql server系統會為每一個索引自動建立一個統計資訊,檢驗方法如下:

查詢結果如下圖所示:

SQL Server · 特性介紹 · 統計資訊

在上面的例子中,當我們手動建立索引時,sql server會為我們手動建立一個同名的統計資訊。其實,當我們執行一個精确查詢語句時,查詢優化器會判斷謂詞中使用的到列,統計資訊是否可用,如果不可用則會單獨對每列建立統計資訊。這些統計資訊對建立一個高效的執行計劃非常必要。

當執行了精确查詢以後,發現多了一個名為_wa_sys_00000002_1d114bd1的統計資訊,這個統計資訊就是sql server自動為我們建立的,因為我們開啟了自動建立統計資訊的選項。

SQL Server · 特性介紹 · 統計資訊

在很多時候,我們需要使用create statistics語句手動建立統計資訊。為了重制這種場景,我們再次手動關閉資料庫adventureworks2008r2的auto create statistics選項,然後再執行anotherid列上的精确查詢。

查詢語句的執行計劃會有統計資訊缺失的警告(missing statistics warnings),如下圖所示:

SQL Server · 特性介紹 · 統計資訊

那麼這個時候就需要我們在anotherid字段上手動建立統計資訊:

sql server除了自動更新統計資訊以外,當我們發現統計資訊過期時,也可以手動更新統計資訊。在講手動更新統計資訊之前,首先我們來看看如何發現過期的統計資訊。

更新統計資訊最需要回答的第一個問題是:我什麼時候需要更新我的統計資訊呢?以下幾種場景,請考慮更新統計資訊:

當大量資料更新(insert/delete/update)到升序或者降序的列時,更新統計資訊。因為在這種情況下,統計資訊直方圖可能沒有及時更新。

強烈建議在除索引維護(當你重建、整理碎片或者重組索引時,資料分布不會改變)外的維護工作之後更新統計資訊。

如果資料庫的資料更改頻繁,建議最低限度每天更新一次統計資訊。資料倉庫可以适當降低更新統計資訊的頻率。

當執行計劃出現統計資訊缺失警告時,需要手動建立統計資訊,在“手動建立”章節就屬于這種情況。

過期的統計資訊會引起大量的查詢性能問題,沒有及時更新統計資訊常見的影響是優化器選擇了次優的執行計劃,然後導緻性能下降。有時候,過期的統計資訊可能比沒有統計資訊更加糟糕。是以,我們可以使用系統視圖sys.stats和系統函數stats_date來擷取到統計資訊最後更新的時間。假如我們定義超過30天未更新的統計資訊算過期的話,那麼查找過期的統計資訊語句如下:

adventureworks2008r2資料庫下過期的統計資訊截圖:

SQL Server · 特性介紹 · 統計資訊

查找到過期的統計資訊以後,接下來需要手動更新統計資訊,我們可以從下面三個次元來達到目的:

更新索引級别統計資訊

更新單表級别統計資訊

更新整個資料庫級别統計資訊

從上面章節我們可以做到更新單索引,表級别和資料庫級别統計資訊,那麼如何快速的更新整個執行個體級别的所有表統計資訊呢?我們可以使用系統存儲過程sys.sp_updatestats和微軟未公開的存儲過程sys.sp_msforeachdb來周遊更新整個執行個體級别統計資訊。

這篇文章從什麼是統計資訊,統計資訊的作用,統計資訊對查詢的影響,如何設定資料庫統計資訊更新政策,如何建立統計資訊,以及如何更新統計資訊等角度,方方面面了解了sql server統計資訊這個躲在幕後的英雄。