慢查詢 - 估計行和實際行之間的巨大差異
在我的工作中,我們遇到了搜尋查詢問題。
如果我不包含查找
Table_39
(請參閱下面的查詢),則執行查詢需要 0 秒。如果我包括查找 (..AND (Not Exists(Select 1 From Table_39 ll ..
),則需要 4 分 57 秒。從執行計劃中我可以看到預期行數和實際行數之間存在巨大差異,特別是在索引中
Table_39
(估計為 62.6 與 10,956,165),所以我嘗試執行UPDATE STATISTICS WITH FULLSCAN
,但沒有任何區別。對於如何提高包含查找的查詢的性能,我將不勝感激!
詢問:
select [Table_2].Gid into #Table_1 from [Table_2] where [Table_2].Gid_Line in ('{31445a8f-900b-4d64-b72f-4e2ac10fd6a7}') union select '{31445a8f-900b-4d64-b72f-4e2ac10fd6a7}' as Gid create unique nonclustered index temp_Table1 on #Table_1 (Gid) go select top 500 Table_9.Id , Table_9.Gid , Table_9.name , Table_9.TimeEnter , Table_9.Prio , Table_9.Direction , Table_9.status , Table_9.CreaterId , Table_9.Subject , Table_9.BodyType , Table_9.Attach , Table_9.FromAddr , Table_9.ToAddr , Table_9.Gid_LineSet , Table_9.xml from Table_9 where Table_9.Gid_LineSet in ( select Gid from #Table_1 ) and not exists ( select 1 from Table_39 ll where ll.Id_Obj_To = Table_9.Id and ll.Id_ObjType_To = 5 and ll.Id_ObjType_From = 3 and ll.Id_Obj_From in ( 9602, 10661, 10857, 10858, 10859, 68823 , 68824, 68825, 68826, 68827, 68828, 68829 , 68830, 68831, 68832, 68833, 68834, 372513 ) ) order by Table_9.Id desc drop table #Table_1
慢查詢的執行計劃(帶查找):https ://www.dropbox.com/s/rc1i6vvdwwc5hzh/long%20query_Cleaned.sqlplan?dl=0
快速查詢的執行計劃(無查找): https ://www.dropbox.com/s/bjafn5tiy3uepul/short%20query_Cleaned.sqlplan?dl=0
行目標
估計的問題很可能是由於
TOP (500)
. 看:
TOP
如果您發現沒有或通過添加OPTION (QUERYTRACEON 4138)
到查詢中的估計要好得多,那將證實該假設。跟踪標誌 4138 記錄在 KB 2667211 中:
如果查詢優化器在 SQL Server 2008 R2 或 SQL Server 2012 中使用 Top 運算符,則查詢可能需要很長時間才能執行。
您還應該使用跟踪標誌 4199 啟用優化器修復。
索引
考慮在表 39 上創建索引,鍵入:
Id_Obj_To, Id_ObjType_To, Id_ObjType_From, Id_Obj_From
確保
Id_Obj_From
具有合適的數據類型(例如max
類型)。預測排序
NOT EXISTS
優化器在您的 SQL Server 版本中不能很好地重新排序子句。如果您希望NOT EXISTS
子句比謂詞更具選擇性,請在查詢部分Gid_LineSet
重新排序這兩個子句。WHERE
我還沒有看到執行計劃,連結不起作用。
當您執行 where not in Table_39 時,它將返回所有行。嘗試將 Table_39 中的數據放入基於“And ll.Id_Obj_From in(9602,10661,10857,10858,10859,68823,68824,68825,68826,68827,68828,68829,68830,68831,68832, 68833,68834,372513)"
這將是一個較小的表,可以駐留在記憶體中,而不是寫入 tempdb。只獲取您需要的列並將它們放入臨時表中。
例如,如果它們是 INT 並且將駐留在記憶體中,我可以將 1000 行放入臨時表中。但是,如果我將每行 20 Meg 的 2 行 XML 放入一個臨時表中,它將被寫入 tempdb。這是一個誇張的範例,但關鍵是臨時表是駐留在記憶體中還是寫入 tempdb 取決於數據的大小。