2011-07-25 115 views
2

在C#程序中,我有一個包含大約100.000個元素的數組。將數組與一個「非常大」的SQL Server數據庫表進行比較

然後,我有一個SQL Server 2008表,其中主鍵列包含或多或少幾乎所有的數組元素(但有一些不是)。該表最多可以有30,000.000行。

現在我想確定數組中哪些元素不存在於表中。如何有效實現這一點?

+1

所有的本地身份證是完全隨機的,還是它們發生在相對體面的連續羣體中? – MatBailie

回答

9

最有效的方法可能是將這些100,000個元素批量插入臨時表中,然後在數據庫中執行比較。

(請注意,我沒有測試這個理論,它只是一個猜測。)

+0

+1服務器速度更快,數據庫索引更好,最重要的是將100K元素移動到服務器比將C元素處理移動到30M元素要便宜。也就是說,DBA可能會對這種方法感到不滿。 – sgtz

+0

是否有任何批量插入記錄的原因,而不是僅僅創建一個巨大的WHERE IN(,,,)? – Rob

+0

'WHERE IN'方法將產生100,000個ID的列表。如果它們都是6位數字,則IN子句的SQL字符串長度將爲700,000個字符。您可能會發現提交大型失敗的查詢。 – MatBailie

1

查詢表與

select <primarykey> where <primarykey> in (<primary key of ur list of elements in c#>) 

這應該是不是插入的所有行插入表更快然後檢查丟失元素的except/minus命令,因爲它不涉及任何寫入操作。

一旦你有主鍵的列表是common.pull它回到c#和比較。

0

避免創建臨時表的一種方法是使用接受用戶定義表類型(udtt)的表值參數的存儲過程。這個表格將有一個數據類型的一列與您的數組中匹配的模式。

如果使用數組值填充DataTable(使用與udtt模式匹配的模式)並將數據表作爲存儲過程的參數提供,那麼可以將所有100,000個項目以sql二進制格式傳遞。 proc可以在30M行表和表值參數之間進行連接,返回TVP表中沒有匹配的表中的項目。

這避免了需要構建大量的IN語句。

編輯關於從@Kyro下面

我現在在這種方法缺乏自信的評論。我發現an article顯示了Kyro描述的行內插入內容。在通過網絡發送二進制數據而不是大型TSQL where in()聲明中,您可能會獲得什麼,可能會被性能SQL方面帶走。然而,這是一個相當簡單的代碼方法,所以可能只是值得快速測試。讓我們知道您的身體情況如何?

+0

這是理論上最好的答案,雖然我發現TVPs在實踐中的速度令人難以置信。 OP應當確定不同的建議方法的基準,並確定哪一個最適合他們以及他們的特定設置。 – LukeH

+1

實際上,對於100,000個元素,表值參數的性能會非常差,特別是如果他針對位於不同計算機上的數據庫運行時。原因是它將在該tabled值參數中運行100,000個插入命令。 SqlBulkCopy將能夠更好地工作,因爲他可以插入臨時表(如果需要放置一個索引),然後在同一連接上運行一個簡單的SQL語句,如 SELECT t.MyKey FROM #Temp t LEFT JOIN s.MeyKey = t.MyKey WHERE s.MyKey IS NULL 然後刪除臨時表並關閉連接。 – Kyro

+0

@LukeH - 我們發現在查詢結尾處有一個OPTION(RECOMPILE)語句可以幫助解決性能問題。這是因爲TVP沒有統計數據,所以SQL假定TVP爲了查詢優化而保持一行。 RECOMPILE生成了一個更好的計劃,並將執行時間從幾分鐘縮短到幾秒鐘。 –

相關問題