2014-06-24 41 views
1

快速注意:我們在內部運行SQL Server 2012,但問題似乎也發生在2008年和2008 R2,或許更早的一些版本。簡單的SQL查詢的性能讓我爲難,

我一直在研究我們的一些代碼性能問題,我已經找到了問題所在以下非常簡單的查詢:

SELECT min(document_id) 
FROM document 
WHERE document_id IN 
    (SELECT TOP 5000 document_id FROM document WHERE document_id > 442684) 

我注意到,這個查詢需要一個荒謬當最終值(在大於)之後大約442000或更大時,長時間(在18s和70s之間,取決於運行它的機器的資源)返回。任何低於此值的查詢都會立即返回。

因爲我已經調整了查詢​​,看起來像這樣:

SELECT min(t.document_id) 
FROM (SELECT TOP 5000 document_id FROM document WHERE document_id > 442684) t 

這立即返回,我已經與測試>的所有值。

我已經解決了手頭上的性能問題,所以我非常高興,但我仍然困惑於爲什麼原始查詢對442000執行得如此糟糕,以及爲什麼它實際上快速運行的值低於(400000 ,350000等)。

任何人都可以解釋這一點嗎?

編輯:修正了第二次查詢是最小的,而不是MAX(這是一個錯字)

+2

你應該在子查詢的'ORDER'條款運作良好,沒有它的結果不能保證每次都相同。 –

回答

2

這是一個評論太長。

的祕訣,瞭解在SQL Server(和其他數據庫)性能的執行計劃。您需要查看查詢的執行計劃才能瞭解正在發生的事情。

查詢的第一個版本有一個連接操作。帶子查詢的IN是另一種表達JOIN的方法。 SQL Server有幾種實現連接的方式,例如散列匹配,合併排序,嵌套循環和索引查找操作。優化器選擇它認爲最好的那個。

沒有看到執行計劃,我最好的猜測是優化改變主意,以最好的算法,以用於in。根據我的經驗,這通常意味着它從一個更合理的切換到嵌套循環算法。

+0

感謝您的支持。我認爲這是SQL Server的底層怪癖,我有一種直覺,認爲它與IN子句相關。我不覺得需要深入上述每個版本的查詢的執行計劃。我很高興知道這是性能問題所在。再次感謝。 –

+1

@ user3771607。 。 。我不得不處理系統,在這些系統中,這些更改會在2分鐘內查詢到。 。 。好吧,沒有完成過夜,並殺死了夜間批量運行。隨着您繼續使用SQL Server,您可能想了解查詢計劃和優化器提示。 –

+0

@Gordon_Linoff感謝您的提示。隨着數據庫開發的進展,我一定會對自己的查詢計劃和優化器提示進行教育。我花了比我們更長的時間來追蹤這個問題。 –

0

查詢從文件更改爲

選擇分鐘(DOCUMENT_ID)其中DOCUMENT_ID> 442684

的選擇中(選擇頂部5000)是SQL一個壞主意 - 如果測試中,它可以擴展到5000 。不知道爲什麼,優化的MAX()的情況下

+0

謝謝,這絕對是找到大於x的最小文檔ID的更智能的方法。我會實現這一點。我們也(在單獨的查詢中)在接下來的5000個文檔中找到最大的文檔ID,這些文檔的ID大於所提供的數字,所以我相信我必須在該查詢中保留「前5000名」。 –

+0

你確定這是它在做什麼?既然你沒有ORDER BY,它可以是任何5000行。 –