Sql Server優化---統計信息維護策略

 

本文出處:http://www.cnblogs.com/wy123/p/5748933.html 

html


首先解釋一個概念,統計信息是什麼:
  簡單說就是對某些字段數據分佈的一種描述,讓SQL Server大概知道預期的數據大小,從而指導生成合理執行計劃的一種數據庫對象算法

默認狀況下統計信息的更新策略:
  1,表數據從0行變爲1行
  2,少於500行的表增長500行或者更多
  3,當表中行多於500行時,數據的變化量大於500+20%*表中數據行數sql

非默認狀況下,促使已有統計信息更新的因素(包括但不限於下面三種,別的我也沒想起來):
  1,rebulid\Reorg index
  2,主動update statistics
  3,數據庫級別的sp_updatestats

數據庫

開始問題:服務器

對於大表的更新策略是:數據的變化量大於500+20%*表中數據行數
好比對於1000W數據量的表,數據變化要超過500+1000W*20%=2,000,500以後才能觸發統計信息的更新,
這一點大多數狀況下是沒法接受的,爲何?由於該規則下觸發統計信息更新的閾值太大,會致使某些統計信息長期沒法更新,
因爲統計信息致使的執行計劃不合理的狀況已經在實際業務中家常便飯,對於統計信息的更新已經顯得很是必要sqlserver

同時,僅僅靠sqlserver本身更新統計信息,也不必定可靠,由於統計信息中還要一個取樣行數的問題,這個也很是重要
由於SQL Server默認的取樣行數是有上限的(默認取樣,未指定取樣百分比或者SQL Server自動更新統計信息時候的取樣百分比),
這個上限值在100W行左右(固然也不願定,只是觀察),對於超過千萬行的表,這個取樣比例仍是很是低的
好比下圖超過3億行的表,更新統計信息時候未指定取樣百分比,默認取樣纔去了84萬行)
據樓主的觀察看,對於小表,不超過500W行的表,默認的取樣比例是沒有問題的,對於較大的表,好比超過500W行的表(固然這個500W行也是一個參考值,不是絕對值)
所以說默認取樣比例是根本沒法準確描述數據分佈的。性能

由此看來,人工介入統計信息的更新是很是有必要的。那麼如何更新索引的統計信息,有沒有一種固定的方式?答案是否認的。優化

 

首先來看可以觸發統計信息更新的方式 ui

1,Rebulid\Reorg index
  固然Rebulid\Reorg索引只是附帶更新了索引的統計信息,主要是爲了整理了索引碎片,
  對於大表,代價至關大,數據庫的維護策略,沒有一律而論的方法,
  對於較小的數據庫或者是較小的表,好比幾十萬幾百萬的表,天天一個rebuild index均可以,
  可是這種經驗移植到大一點的數據庫上恐怕就很差使了(正如名人的成功經驗不可複印同樣,每一個人生活的環境不同,不能一律而論)。
  這種Rebulid\Reorg index對資源的消耗以及時間代價上都會至關大,甚至有些狀況下是不會給你機會這麼作的。
  好比下面rebuild一個複合索引的耗時狀況,僅僅是一個表上的一個索引,就花費了5分鐘的時間
  一個業務複雜的表上有相似這麼三五個索引也是正常的,
  照這麼算下去,若是全庫或者是整個實例下的十幾個庫,每一個庫數百張表所有這麼作,要多長時間,代價可想而知
  說不定整都沒整完,維護窗口期的時間就到了,除非數據庫不大(究竟大小的臨界值爲多少?我的以爲能夠粗略地認爲100GB吧),不然是不能夠這麼作的。spa

  所以能夠認爲:經過重建或者重組索引來更新索引統計信息,代價太大了,基本上是不現實的。

  


2,update statistics

  正是我想重點說的,由於我這裏不具體說語法了,具體語法就不作詳細說明了,
  簡單來講,大概有以下幾種選擇:
  一種默認方式,另外還能夠是全表掃描的方式更新,還有就是是指定一個取樣百分比,以下:

--默認方式更新表上的全部統計信息
update statistics TableName
--對指定的統計信息,採用全表掃描的方式取樣
update statistics TableName(index_or_statistics__name) with FullScan 
--對指定的統計信息,採用指定取樣百分比的方式取樣
update statistics TableName(index_or_statistics__name1,index_or_statistics__name2) with sample 70 percent

  相對於重建或者重組索引,update statistics 也是經過掃描數據頁(索引頁)的方式來獲取數據分佈,可是不會移動數據(索引)頁,
  這是Update Statistics代價相對於Rebuild索引小的地方(即使是Update Statistics的時候100%取樣)
  關鍵在於第三種方式:人爲指定取樣百分比,若是取樣百分比爲100,那跟FullScan同樣
  若是不用100,好比80,60,50,30,又如何選擇?取樣百分比越高,獲得的統計信息越準確,可是代價越大,取樣越小效率越高,可是偏差的可能性會變大,怎麼辦,這就須要找一個平衡點。
  那麼究竟要取樣多少,既能在更新統計信息的效率上能夠接受,又可以使得統計信息達到相對準確地描述數據分佈的目的,
  這是仍是一個須要慎重選擇的問題,爲何?參考:http://www.cnblogs.com/wy123/p/5875237.html
  若是統計信息取樣百分比太低,會影響到統計信息的準確性,
  若是過於暴力,好比fullscan的方式掃描,
  參考下圖,一個表就Update了50分鐘(固然這是一個大表,上面有多個索引統計信息以及非索引統計信息)。若是有數十張相似的表,效率可想而知
  總之就是,沒有一個固定的方式,數據庫不大,怎麼作問題都不大,數據庫一大,加上維護的窗口期時間有限,要在統計信息的質量和維護效率上綜合考慮

  

 

3,數據庫級別的sp_updatestats

  用法:
  exec sp_updatestats
  或者
  exec sp_updatestats @resample = 'resample'

  指定 sp_updatestats 使用 UPDATE STATISTICS 語句的 RESAMPLE 選項。

  對於基於默認抽樣的查詢計劃並不是最佳的特殊狀況,SAMPLE 很是有用。
  在大多數狀況下,沒必要指定 SAMPLE,
  這是由於在默認狀況下,查詢優化器根據須要採用抽樣,並以統計方式肯定大量樣本的大小,以便建立高質量的查詢計劃。

  若是未指定 'resample',則 sp_updatestats 將使用默認的抽樣來更新統計信息。 
  默認值爲 NO。

  直接執行exec sp_updatestats更新統計信息,取樣密度是默認的,
  究竟這默認值是多少,MSDN上說默認狀況下是「查詢優化器根據須要採用抽樣」,我想着採樣算法應該沒那麼簡單粗暴
  目前也不知道具體是怎麼一個算法或者採樣方式,若是有知道園友的話請不惜賜教,謝謝

 

4,TraceFlag 2371

開啓TraceFlag 2371以後,統計信息的變化是根據表作動態變化的,
打破了觸發大表統計信息更新的當表中行多於500行時,數據的變化量大於500+20%*表中數據行數 閾值
參考:https://blogs.msdn.microsoft.com/saponsqlserver/2011/09/07/changes-to-automatic-update-statistics-in-sql-server-traceflag-2371/

  在下圖中,你能夠看到新公式的工做方式,對於小表,閾值仍舊是在20%左右,
  只有超過25000行以後,此動態規則纔會被觸發生效
  隨着表中數據行數的增長,(觸發統計信息變動)的百分比會變的愈來愈低,
  好比,對於100,00行的表,觸發統計信息更新的閾值已經下降爲10%,
  對於1,000,000行的表,觸發統計信息更新的閾值已經下降爲3.2%。

  

  對於10,000,000或者是50,000,000行的表,觸發統計信息更新的閾值爲少於1%或者0.5%,
  而對於他100,000,000行的表,僅僅要求變化在0.31%左右,就能夠出發統計信息的更新。

  可是我的認爲,這種方式也不必定靠譜,雖然開啓TraceFlag 2371以後觸發更新索引統計信息的閾值下降了,可是取樣百分比仍是一個問題,
  以前我本身就有一個誤區,看統計信息的時候只關注統計信息的更新時間(跟本身以前遇到的數據庫或者表過小有關)
  對於統計信息,及時更新了(更新時間比較新)不等於這個統計信息是準確的,必定要看取樣的行數所佔總行數的百分比

 

如何有效維護索引統計信息?

  上面說了,要使獲取相對準確的統計信息,就要在更新統計信息時候的取樣百分比,
  對於小表,即使按照其默認的變化閾值觸發統計信息更新,或者是按照100%取樣更新統計信息,都是沒有問題,
  對於大表,必定要考慮在其達到默認觸發統計信息更新的閾值以前人爲更新這個統計信息,可是大表的100%取樣統計是不太現實的(性能考慮)
  取樣百分比越高,獲得的統計信息越準確,可是代價越大,這就須要找一個平衡點,那麼若是更新大表上的統計信息呢?
  若是是認爲干預統計信息的生成,就要考慮兩個因素:一是數據變化了多少以後更新?二是更新的時候,以什麼樣的取樣來更新?
  咱們知道,一個表的數據變化信息(增刪改)記錄在sys.sysindexes這個系統表的rowmodctr字段中,
  該表的統計信息更新以後,該字段清零,而後再次累積記錄表上的數據變化。

  

  這個信息很是好使,爲人工更新統計信息提供了重要的依據,
  好比,對於1000W行的表,能夠指定變化超過20W行(根據業務狀況自定義)以後,手動更新統計信息,
  對於5000W行的表,能夠指定變化超過60W行(根據業務狀況自定義)以後,手動更新統計信息,
  同時根據不一樣的表,在相對較小的表上,指定相對較高的取樣百分比,在相對較大的表上,指定相對較低的取樣百分比
  好比對於1000W行的表,更新統計信息的時候取樣百分比定位60%,對於5000W行的表,更新統計信息的時候取樣百分比定位30%
  這樣,能夠自行決定數據變化了多少以後更新統計信息,以及動態地決定不一樣表的不一樣取樣百分比,達到一個合理的目的。
  固然,最後強調一下,我說的每個數據都是相對的,而不是絕對的,都是僅作參考,
  具體還要你本身結合本身的服務器軟硬件以環境及維護窗口時間去嘗試,一切沒有死的標準。

 

總結:統計信息的準確性對執行計劃的生成有着相當重要的影響,本文粗略分析了統計信息的跟新規律以及要更新統計信息時候要注意的問題,   在人爲干預統計信息更新的時候,須要根據具體的狀況(表數據流量,服務器軟硬件環境,維護窗口期等)在效率與準確性之間做出合理的選擇。

相關文章
相關標籤/搜索