SQL Server 優化---為什么索引視圖(物化視圖)需要with(noexpand)強制查詢提示


 

 

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

 

第一次通過索引視圖優化SQL語句,以及遇到的一些問題,記錄一下。

 

語句分析

最近開發遞交過來一個查詢統計的SQL,說是性能有問題,原本執行需要4-5秒鍾,這個業務本身對性能要求又比較critical,期望是在1s之內 在用盡各種辦法之后(執行計划,統計信息,索引,改寫SQL,臨時表拆分),依然沒有實質性的改觀, 在觀察SQL本身的特點之后, 有以下幾個特點   1,查詢語句整體為多表join,但是每個表自身的數據並不是非常大,百萬級   2,查詢結果在主表上一個較大的時間范圍的數據進行Count的聚合操作   3,幾張表之間除了連接條件,主要是進行了一些比較復雜的邏輯運算(下面截圖可以看到,沒多少IO,CPU時間卻很高)        不過表的連接方式都是inner join,主要性能點就在於表關聯之間的Hash join之間的邏輯運算,參考下圖(是執行計划的一部分)

  通過統計信息發現,該SQL語句的物理IO並不高,說明索引沒有什么問題,通過索引改善IO可能改善空間很有限   時間主要花費在SQL語句的編譯和的Hash join 運算   嘗試改寫借助SQL之后(純改寫SQL和借助臨時表拆分語句),發現依然很難繞過Hash join,主要是表之間的邏輯運算最為耗時   最后想到可以先將運算好的的數據物理存儲起來,然后改寫查詢的SQL語句完成等價的查詢,      避免每次查詢都做復雜的邏輯運算,應該可以有比較大的改善,於是就想到了索引視圖

  

創建索引視圖改寫SQL

  在提取出來原始的查詢SQL,創建索引視圖,並在索引視圖上創建unique cluster index和合理的nocluster index   通過索引視圖改寫原始的查詢統計SQL語句,   改寫后的SQL語句是一個索引視圖替代原始的4張表,與另外一個物理表join,發現效率上沒有任何改善,   觀察改寫后的SQL語句的執行計划,發現跟原始SQL一樣,並沒有走索引視圖上的索引,或者說是用到索引視圖,一時間覺得好心塞,實在沒招了   執行計划依舊是長長的一大段,然后依舊是好幾個Hash Join.參考下圖,執行計划跟本文第一個截圖一模一樣

  按道理,索引視圖固化結果集,並且根據情況做了過濾,結果集是原始查詢的一部分而已,   用同樣的查詢條件從索引視圖做查詢統計,走索引視圖代價肯定要比原始SQL低,通過強制不展開with(noexpand)提示,證實了這個推斷   如下是強制不展開索引視圖的統計信息,可以看到完全達到了預期的1S之內

  

 

  當然索引視圖也不是沒有代價,在一定程度上犧牲了數據寫入的效率和冗余存儲,來換取查詢的效率   之前簡單介紹過索引視圖的一些特點 http://www.cnblogs.com/wy123/p/6041122.html

 

索引視圖被展開(expand)的原因分析

  最關鍵的問題在於,沒有強制不展開索引視圖(with(noexpand)提示)的情況下,為什么沒有走索引視圖呢?

  這個問題確實郁悶了一陣子,整個半天都在想這個問題,因為索引視圖本身用的就少,出現此問題更是一頭霧水,不過Google一下,還有一大把類似的問題   如下是在google的時候查到的,原文是英文,大概意思如下,非直譯。

  參考鏈接:http://dba.stackexchange.com/questions/26979/what-factors-go-into-an-indexed-views-clustered-index-being-selected/27039#27039

索引視圖的匹配(查詢用索引視圖替代而不走原始的基礎表)是一個相當昂貴的操作,因此優化器試圖通過其他方式快速轉換(生成執行計划) 如果優化器產生了一個相對優化的執行計划,就可以盡早結束(不必繼續生成其他執行計划) 問題就在於:繼續生成其他執行計划的代價要大於已生成的執行計划的代價 聽起來有點別扭, 之前舉過這么一個例子,比如說是花3秒鍾找到一個相對優化的執行計划,這個執行計划完成SQL的執行需要2秒鍾 與花10秒鍾的時候找到一個最優化的執行計划,盡管這個執行計划完成SQL的執行可能只需要0.5秒鍾,雖然后者的執行計划更優,但整體代價更大 優化器的主要目標是盡快找到一個足夠好的執行計划(而非總是生成最好的執行計划)

使用索引視圖本身並不是一個昂貴的操作, 但是與潛在索引視圖中匹配邏輯查詢樹確實一個代價較大的行為,在查詢涉及的視圖在優化器優化之前已經被展開 因此優化器並不知道你的查詢是否未被了索引視圖,他看到的只是展開的查詢樹 這個通俗地講就是: 讓sqlserver知道,一個查詢,可以用索引視圖中的結果等價替代視圖邏輯中原始的基表,是一個代價較大的過程 因為SQL Server根據原始的基礎表,生成一種執行計划之后,就不去判斷是否可以用索引視圖做等價替代。

   當然白皮書里有更詳細的介紹,里面索引視圖相關的一些邏輯實現和分析http://www.cs.cmu.edu/~natassa/courses/15-823/current/papers/vldb00.pdf

 

最后多逼逼一句:   上面的白皮書實在看不懂,只是Google出來說詳細信息請看這個參考資料,   這里只是從現象去推斷優化器在面對索引視圖的一些特性,了解到內在機制的一些特點,可能潛在的問題,以及對應的解決辦法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM