記一次SQLSERVER2008R2資料庫查詢超時問題處理
資料庫環境:
WINDOWS2008R2
SQLSERVER2008R2
應用程式環境:
REDHAT6.5
TOMCAT
JAVA
一、故障現象
某系統應用查詢超時
相關SQL:
SELECT v.OBarcode Barcode, v.CBarcode, v.ZID, v.FromName ZNAME, v.ItemName, v.Batch, v.OrderNo, v.SussDate createddate FROM V_TrackAllShipment v (NOLOCK) WHERE 1=1
AND v.OBARCODE = '13436135998'
其中V_TrackAllShipment是一個檢視,且該視圖裡面還有一個檢視,兩個檢視中均運用了大量的union(最多有9個)
該SQL在應用程式查詢超時報錯,無法得到查詢結果,但直接在資料庫中查詢可以在幾秒內得到查詢結果,且結果返回只有幾行資料
二、問題分析
1、嘗試去掉1=1永真條件,查詢依然超時
2、嘗試去掉1=1永真條件,加上1<>1永假條件,幾秒內查詢成功,但返回結果為0行
3、嘗試去掉所有的where條件,幾秒內查詢結果返回50行
三、使用profiler跟蹤應用程式查詢SQL
1、跟蹤該SQL後,發現應用程式執行到資料庫的SQL語句發生變化,如下:
SELECT top 50 v.OBarcode Barcode, v.CBarcode, v.ZID, v.FromName ZNAME, v.ItemName,
v.Batch, v.OrderNo, v.SussDate createddate
FROM V_TrackAllShipment v (NOLOCK) WHERE 1=1
AND v.OBARCODE = '13436135998'
多了top 50關鍵字
2、分析執行計劃
帶有top 50關鍵字的SQL執行計劃,預估行數達到1億多行,且索引失效
原SQL沒有帶top 50關鍵字的,預估行數只有幾行
四、結論
應用程式在執行SQL的時候,向SQLSERVER資料庫自動添加了top 50關鍵字,導致執行計劃改變,查詢超時
五、思考
為何去掉where條件後,查詢結果在幾秒內返回呢?原因在沒有where條件的時候 top 50就只是根據一個ID 選擇前面幾個,但是有where 條件之後,top 50是先需要根據where條件進行查詢出來之後,再把資料進行排序 然後top條資料
六、解決方案
1、在應用程式上去掉top 50
2、我嘗試執行UPDATE STATISTICS dbo.tfacsalebarlib WITH FULLSCAN; 進行統計資訊收集後,執行計劃居然變正確了(該表是where條件那個欄位對應所在的表)