SQL Server中不少怪異問題都是由用錯關聯方式引起的,從2000到2005有所改善,但2005的查詢最佳化引擎還是存在“犯傻”的時候
1. 問題1
現象:一個預存程序,通過一個服務程式調用,長時間不能結束,資料庫伺服器顯示該預存程序執行到某個語句時一直等待在那,資料庫伺服器記憶體充足,CPU消耗幾乎沒有。把這個預存程序拿出來直接在查詢分析器中執行,參數跟程式調用時完全類似,立即結束且結果正確
解決方案:排除了阻塞等原因,因為放在查詢分析器中執行時一切正常,從執行計畫等方面無法看出任何問題,也排除了磁碟IO等方面的原因,實在想不到其他的了。最後懷疑是SQL Server查詢引擎JOIN方式選的不對,強制使用HASH JOIN後,程式調用恢複正常
疑點:一直沒有發現程式調用與直接使用查詢分析器執行,這2者之間存在哪些差別,會影響到SQL Server查詢最佳化決策
2. 問題2
現象:一個不算複雜的查詢,用到了row_number函數分頁,一執行就會導致伺服器8個CPU全部100%,很長時間(好幾分鐘)不能結束。使用暫存資料表實現同樣的效果,幾秒鐘完成
語句1:
SELECT
ROW_NUMBER() OVER(ORDER BY COLUMNNAME1 ASC) as FC_ROWNUMBER
,COUNT(1) OVER() AS FC_COUNT
,* FROM (
SELECT 產品 as COLUMNNAME1,產品描述 as COLUMNNAME2,入庫日期 as COLUMNNAME7,預期數量 as COLUMNNAME8
,入庫數量 as COLUMNNAME9,行狀態 as COLUMNNAME10,供應商 as COLUMNNAME11,供應商名稱 as COLUMNNAME12
FROM V_收貨明細查詢
where 入庫日期 >= '2010-7-1'
) TT_MAINKEY_TMP
執行計畫:
語句2:
SELECT * FROM (
SELECT
ROW_NUMBER() OVER(ORDER BY COLUMNNAME1 ASC) as FC_ROWNUMBER
,COUNT(1) OVER() AS FC_COUNT
,* FROM (
SELECT 產品 as COLUMNNAME1,產品描述 as COLUMNNAME2,入庫日期 as COLUMNNAME7,預期數量 as COLUMNNAME8
,入庫數量 as COLUMNNAME9,行狀態 as COLUMNNAME10,供應商 as COLUMNNAME11,供應商名稱 as COLUMNNAME12
FROM V_收貨明細查詢
where 入庫日期 >= '2010-7-1'
) TT_MAINKEY_TMP
) TT_RET_TMP
WHERE FC_ROWNUMBER BETWEEN 1 AND 1000
ORDER BY COLUMNNAME1 ASC
執行計畫:
僅僅是把SQL作為一個子查詢,在外面多封裝了一下,整個查詢計劃就不一樣了。排除了統計資訊不準確、索引片段等狀況
2個查詢計劃中對3個表使用的都是叢集索引掃描,基本上就是關聯演算法不一樣
因為用的並行查詢,三個表資料都有幾十萬和一百多萬,嵌套迴圈需要執行幾十萬次,所以單個查詢導致所有CPU都100%。估計高CPU是由於Lazy Spool操作造成的
解決方案:
強制用HASH JOIN,或者加索引避免SQL Server出錯,或者用暫存資料表繞過去