SqlServer 索引自動最佳化工具

來源:互聯網
上載者:User

鑒於人手嚴重不足(當時算兩個半人的資源),打消了逐個庫手動去改的念頭。當前的程式結構不允許搞革命的做法,只能搞搞改良,所以準備搞個自動化工具去處理。原型剛開發完,開會的時候以拿出來就遭到營運DBA團隊強烈抵制,具體原因不詳。最後無限延期。這裡把思路分享下。歡迎拍磚。

  整個思路是這樣的,索引都是為查詢和更新服務的,但是不合適的索引又會對插入和更新帶來負面影響。面對錶上現有的索引想識別那些是有效不太可能。那麼根據現有的資料使用方式重建所有的新索引不就解決了嘛。根據查詢產生全新索引,然後和現有對比,不吻合的全部刪除,原來沒有的建立。雖然說對於正在啟動並執行系統來說風險還是蠻大的。但是可以做臨界測試嘛。
  
具體解決方案如下:

  首先在熱備的資料庫伺服器上定期抓取緩衝的執行計畫(原本想抓取SQL發現有些SQL實在摻不忍睹,沒有自動化解析的可能性),然後連同該執行的執行次數即表的統計資訊一起down到一個待命伺服器的資料表中。

  執行計畫積累幾次後,開始解析。由於執行計畫是格式良好的XML檔案,加上微軟提供執行計畫的XSD檔案。我們可以反向推出各節點對應的SQL謂詞(這個XSD到現在都沒找到官方的說明,只能反向推出關聯)。例如建立索引我們比較關心三類謂詞,分別為:Select,Join,Where。 只要拿到這些我們就能建立良好的索引。原理很簡單,Join和Where都是索引鍵的依據,而Select可以斟請添加到Index的Include中。
  
  解析的時候也不是針對單個執行計畫,而是將所有執行計畫全分解後進行統計處理。好處就是能夠知道那些表欄位被引用的最多,那些是外鍵列。那些資料被反覆查詢。例如可以得出TableA的Col1列在一天的業務過程中被Join了10W次,被Where2W次。而Col2則被Select了10W次,僅僅被Where了100次。這樣我們建立索引的基礎就是基於表的而不是基於單個查詢的。最終產生的Index將權衡查詢頻率和查詢的重要性,如果某個業務查詢特別重要,但執行頻率不高我們可以提供權重,優先建立索引。當然建立Index還要參考表的資料分布以決定Index中欄位的順序。

  好了,準備工作完成,開始建索引。當前擁有的條件,表資料分布,表欄位分別被查詢引用次數(Select,Join,Where),以及這些SQL謂詞出現的次數。根據這些如何建立索引開始的想法是逐個分析,考慮所有可能性然後建立。發現這種方式只適合人腦,讓電腦做得先讓電腦的智商增長到120以上才有可行性。發現逆向思維這裡同樣大有用處,既然不能一下子建立最合適的,那我們就根據執行計畫得出的組合建立所有的Index組合。凡是Join和Where都放到Index的Key裡。例如:
  select t1.A, t1.B, t1.C, t2.J, t2.k from Table1 t1 Join Table1 t2 on t1.A = t2.j Where t1.A = 'param'

草創的索引就是:

  Index(A,B)includ(C) 和 Index(j)include(j,k)

關於Select如果是小資料類型且Alter的執行計畫中該資料修改頻率很小的都放到Include裡去進去。大資料類型和修改比較頻繁的就算了。這樣我們剔除相互覆蓋的。部分重疊的,部分重疊到底保留那一個參考執行頻率和查詢重要性。差異很小的就合并並為一個,如:

  1.Index (A,B,C)Include(D)
  2.Index(A,B,D)Include(C)

直接合并為:

  Index(A,B)Include(C,D)

當然如果Alert的特別少也可以合并成Index(A,B,C,D)這個要參考C,D欄位的修改頻率。和主鍵重疊的剔除。這樣留下的基本上就是我們需要的索引了。
  
  對比現有索引進行甄別覆蓋的過程就略過。簡單的拉出來Create Index 進行解析處理就好了。發布的時候很簡單。寫個指令碼在業務比較少的時候做Drop和Create就完成了。項目原始碼因為設計到公司的保密問題就不上傳了。一個注意的地方對於簡單查詢的SQL執行計畫緩衝的時候會比較短且一旦緩衝不夠就會被清理掉。要注意這些SQL的執行頻率的誤差。

  SqlserverR2 XSD:http://schemas.microsoft.com/sqlserver/2004/07/showplan/sql2008/showplanxml.xsd
 
 總結的節點映射列舉如下:

    查詢sql執行計畫都包含在節點“StmtSimple”中,如果沒有這個節點一般就是其它類型的SQL的執行計畫。

    Join關聯的節點和自身類型有關一般包含在Hash,Marger中,如何Join同時又是Where條件的話則會出現在SeekKey和Compare節點中,因為Join的列都是成對出現,這裡很容易識別,有一個是參數(@開頭)或常量(type="Const")則必定是Where條件。
    
    Select最終輸出欄位比較容易找到,第一個OutputList節點就是。

    需要注意的是有因為一般列每個ColumnReference都包含庫名,表名,列資訊,但是系統資料表則不會。注意剔除。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.