遊標指令碼效能問題解決與分析 (4) - Cursor Performance Analysis
第四部分、遊標相關知識講解
(一)Fast Forward Only(快速只進)遊標分析
Microsoft SQL Server 實現了一種稱作fast forward only遊標的效能優化。http://msdn.microsoft.com/zh-cn/library/ms187502.aspx
當遇到下面情形時,Fast Forward-only遊標會隱式轉換為其他型別
1. 當SELECT語句連線包含trigger table(INSERTED/DELETED)的一個或多個表,遊標被轉換成static型別。
2. 當SELECT語句查閱text、ntext或image列,如果SQL Server OLE DB訪問介面或使用了SQL Server ODBC驅動器,遊標被轉換成dynamic型別。
3. 當Fast Forward-only遊標不是隻讀的,它會被轉換成dynamic遊標。動態遊標是可以用來update當前滾動到的資料行並將更新回寫到table中的。
4. 當SELECT語句是一個查閱了連結伺服器中一個或多個遠端表進行分部查詢,遊標被轉換成keyset-driven型別。
5. 如果SELECT語句查閱text、ntext或image列以及TOP語句,遊標被轉換成keyset-driven型別。
(二)幾種遊標的使用規則:
另外,我們這裡列出了幾條遊標使用規則可供參考:
1. 如果應用程式中,只能使用伺服器端遊標(所有在SQL Server上定義的遊標都是伺服器端遊標,如果應用程式在客戶端使用遊標,在SQL Server端是不會看到有遊標開啟的),儘量選擇使用FORWARD-ONLY、FAST-FORWARD、READ-ONLY遊標。當處理單向只讀資料時,使用FAST_FORWARD選項而不是FORWARD_ONLY,因為它可以提供一些內部的效能優化。這種型別的所遊標產生的SQL Server整體開銷是最少的。如果您無法使用FAST_FORWARD遊標,可以按序嘗試使用下面的遊標,找到適合您需求的遊標。按照他們的效能特徵列出,從最快到最慢為:dynamic,static,keyset。
2. 除非沒有其他選擇,避免使用static/insensitive和keyset遊標,這是因為他們會在TEMPDB中建立臨時表,這會增加整體開銷導致記憶體搶奪問題。
3. 使用遊標會減少並行而導致不必要的鎖和阻塞的發生。要避免這種情況,可以適當地使用READ_ONLY遊標選項;或者在你需要進行更新時,使用OPTIMISTIC遊標選項來減少鎖的產生。避免使用SCROLL_LOCKS遊標選項,因為它會減少並行。
4. 從應用程式的角度儘快的載入並且滾動遊標到最後一行。這會釋放在建立遊標時隨之建立的共享鎖,從而釋放SQL Server資源。
5. 如果你的應用程式需要手動滾動記錄並進行更新而必須使用遊標,請避免使用客戶端遊標,除非返回的行數很少或資料是靜態的。如果行數很大,或者資料不是靜態的,可以考慮使用伺服器端的keyset遊標。由於客戶端和伺服器端網路擁擠的減少,效能問題很可能會出現。為了優化效能,可能需要在實際情況下對兩種遊標型別都進行嘗試,決定哪種更適合需要應用的系統。
6. 如果遊標需要執行JOIN操作,keyset和static遊標通常比dynamic遊標快。
(三)深入瞭解Fast_forward遊標
1. 既然已經有了read_only forward_only遊標,fast_forward遊標豈不是是多餘的?為什麼還需要它們?
fast_forward的確是”多餘”的。read_only forward_only遊標確實適用於很多應用,但是在有些應用的查詢計劃中卻不理想。Read_only forward_only遊標是動態遊標,動態遊標一般使用的是動態計劃。問題在於,有些情況下即使最好的動態計劃也遠不如靜態計劃。因此我們引入了Fast_forward遊標來使用了一種更平衡的方式,當靜態計劃更適合時它會選擇靜態計劃。
2. 什麼時候用fast_forward,什麼時候用read_only forward_only?
綜合來說,fast_forward遊標更好一點。但是,在做最後決定之前應該先對您的應用進行效能測試。這是因為,使用動態或者靜態計劃的決定方式是完全不同的(看下面的解釋)。不論使用哪種計劃方式或哪種遊標模式,索引調優(index tuning)或計劃提示(plan hint)都會是遊標優化的一個重要部分。
3. 什麼是動態計劃?
動態計劃可以增量地進行,在SQL Server中,我們通過將查詢執行狀態序列化到maker中來實現。然後,我們可以構建一個新的查詢計劃樹,使用剛剛的maker來複位每個操作。另外,動態計劃可以根據當前位置前後移動。dynamic和一些fast_forward遊標都會使用動態計劃。
動態計劃只包括動態運算子(支援maker及前後的移動),這很像流操作符中進行查詢的notion(stop-and-go)。但並不是每個流操作符都是動態的。
在SQL Server中,動態意味著:
(1) 操作符可以使用maker復位到它當前的位置,或者到當前位置的相關位置(下一個或前一個)
(2) 操作符狀態一定要小,從而使maker比較小。操作符中不能儲存行資料,尤其是sort table、hash table或者work table,甚至一行都不可以,因為即使單行也可能很大。
沒有動態計劃,遊標可能需要臨時儲存媒介來儲存查詢結果集(或它的keyset)。然而,某些操作符對動態執行計劃來說是不合適的,比如hash join、hash agg、compute sequence和sort。這會導致一個次優的計劃。
4. 什麼時候動態計劃會不如靜態計劃?
在某些查詢中,比如使用row_number的,動態計劃是不可用的。但是當動態靜態都可用時就有問題出現了:在某個操作符(比如join)既有動態(nested loops)也有非動態(hash)實現時可能發生;當有些索引支援排序而有些不支援時,也可能會發生問題。
下面是一個例子,表ORDERS有一個DATE上的索引,以及一個SUBTOTAL上的索引(在這個例子中,clustered或者non-clustered沒關係)。該查詢想要查詢訂單資訊:
SELECT DATE, SUBTOTAL, ORDERID, CUSTOMERID
FROM ORDERS where SUBTOTAL > 10000000
ORDER BY DATE
表中有一億條資料,查詢結果包含100條。動態遊標不能排序,所以它必須使用DATE索引,檢視每條資料,填到SUBTOTAL中。而靜態遊標可以查詢大於10000範圍的SUBTOTAL索引,排序並把它們儲存到遊標(temp table)中。
5. fast_forward遊標如何解決該問題?
在特定條件下,fast_forward遊標從最佳靜態計劃和最佳動態計劃中選擇開銷最小的一個。在上面所提到的極端例子中,它就會使用靜態計劃。
6. 應用開發者可以做什麼?
(1) 為OPTION(FAST
(2) 通過呼叫sp_cursorprepare或OPTION(RECOMPILE)避免在不同引數下的計劃重用。
(3) 避免在遊標中使用ORDER BY
(4) 使用相等謂詞及多列索引來支援序列。稍微修改一下上面的例子,如果我們在SUBTOTAL範圍有一個包含值{S,M,L,XL}的計算列SIZE,我們可以查詢WHERE SIZE=’XL’ ORDER BY DATE,並在
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8183550/viewspace-705773/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 遊標指令碼效能問題解決與分析 (2) - Cursor Performance Analysis指令碼ORM
- SQL 遊標cursorSQL
- 【CURSOR】Oracle 遊標 (cursor)知識梳理Oracle
- PL/SQL 04 遊標 cursorSQL
- 執行 shell 指令碼 \r 問題解決指令碼
- shell指令碼中文註釋亂碼問題(解決)指令碼
- Oracle使用cursor for隱式遊標Oracle
- PLSQL 呼叫 返回 遊標(Cursor)PROCEDURESQL
- SQL 遊標cursor的運用SQL
- Unix shell解決實際問題指令碼(1)指令碼
- Unix shell解決實際問題指令碼(2)指令碼
- Unix shell解決實際問題指令碼(3)指令碼
- 解決img標籤與其它標籤間隙問題?
- oracle cursor遊標迴圈比較遊標元素是否相同Oracle
- Ajax跨越問題原因分析與解決思路
- zt_enqueue:HW問題分析與解決ENQ
- Error in GetCurrentDir(): 13 問題分析與解決Error
- flask-sqlalchemy中使用cursor遊標FlaskSQL
- oracle cursor遊標獲取首末元素Oracle
- Inside MSXML Performance(MSXML效能分析) (4) (轉)IDEXMLORM
- Oracle遊標共享(Cursor Sharing)--常規遊標共享和自適應遊標共享(ACS)Oracle
- crontab不執行mysql的指令碼問題的解決!MySql指令碼
- sybase中cursor的使用中死迴圈問題解決
- 實驗:cursor count超高的問題分析
- 使用 IBM 效能分析工具解決生產環境中的效能問題IBM
- IFrame安全問題解決辦法(跨框架指令碼(XFS)漏洞)框架指令碼
- 一個指令碼解決AD使用者批量操作問題指令碼
- 解決 Python 指令碼無法生成結果的問題Python指令碼
- 解決吞吐效能問題時的思路
- html指令碼 標籤與HTML指令碼
- 【DBA 指令碼】查詢current open cursor的指令碼指令碼
- cursor_顯式遊標_與rhel5的效能關係_plsql_儲存過程_sp_procedureSQL儲存過程
- Java應用上雲後被kill問題分析與解決Java
- 磁碟問題定位與解決
- git合併丟失程式碼問題分析與解決(錯誤操作導致)Git
- 解決“阻塞效應”-解決指令碼檔案下載阻塞網頁渲染的問題指令碼網頁
- 解決中文亂碼問題
- 解決SSH亂碼問題