我知道這個話題已被打死,但似乎互聯網上的許多文章往往尋找最優雅的方式,而不是如何解決它的最有效的方法。這是問題。我們正在構建一個應用程序,其中一個常見數據庫查詢將涉及基於用戶提供的ID列表的操作(SELECT和UPDATE)。有問題的表預計會有數十萬行,用戶提供的ID列表可能無界限,他們最有可能是數十或數百(我們可能會因性能原因而限制它)。在哪裏ID(1,2,3,4,5,...)效率最高?
如果我理解數據庫的工作原理是正確的,那麼最有效的方法是簡單地使用WHERE ID IN (1, 2, 3, 4, 5, ...)
構造並動態構建查詢。問題的核心是ID的輸入列表將是真正任意的,因此無論數據庫有多聰明或者我們實現它的巧妙程度如何,我們總是有一個隨機的子集來開始,所以最終每個方法都必須無論如何,內部歸結爲類似WHERE ID IN (1, 2, 3, 4, 5, ...)
。
人們可以在網絡上找到很多方法。例如,需要聲明一個表變量,將ID列表作爲逗號分隔的字符串傳遞給存儲過程,在存儲過程中拆分它,將ID插入表變量並將主表連接到它上面,即類似這樣的:
-- 1. Temporary table for ID’s:
DECLARE @IDS TABLE (ID int);
-- 2. Split the given string of ID’s, and each ID to @IDS.
-- Omitted for brevity.
-- 3. Join the main table to @ID’s:
SELECT MyTable.ID, MyTable.SomeColumn
FROM MyTable INNER JOIN @IDS ON MyTable.ID = @IDS.ID;
把與字符串操作的問題不談,我認爲實際上發生的事情在這種情況下,在第三步中,SQL Server的說:「謝謝你,這很好,但我只需要列表該ID「,並且它掃描表變量@IDS
,然後n找到MyTable
其中n是該ID的編號。我已經完成了一些基本的性能評估,並檢查了查詢計劃,而這似乎是發生了什麼事情。所以表變量,字符串連接和分割以及所有額外的INSERT都沒有用處。
我正確嗎?或者我錯過了什麼?有沒有真正的一些聰明和更有效的方法?基本上,我所說的是SQL Server必須做n索引搜索,無論是什麼和制定查詢作爲WHERE ID IN (1, 2, 3, 4, 5, ...)
是要求它的最直接的方式。
一個評論我會做,似乎在Web上的搜索中缺少的是,當您爲ID聲明臨時表時,應該將ID列聲明爲主鍵。然後SQL Server在其上放置一個索引。如果你不這樣做,它會進行表掃描,如果表中包含很多行,這會嚴重影響性能。 – 2009-10-05 20:23:18
我不想讓我原來的問題更長,但我也測試了這個。似乎將索引放在ID列上並沒有什麼區別,因爲來自表變量(或臨時表)的所有服務器需求都是其中所有ID的列表。所以在這種情況下索引似乎沒有幫助(或者至少在ID的列表比主表短得多的情況下)。 – 2009-10-05 20:32:46