在C#程序中,我有一個包含大約100.000個元素的數組。將數組與一個「非常大」的SQL Server數據庫表進行比較
然後,我有一個SQL Server 2008表,其中主鍵列包含或多或少幾乎所有的數組元素(但有一些不是)。該表最多可以有30,000.000行。
現在我想確定數組中哪些元素不存在於表中。如何有效實現這一點?
在C#程序中,我有一個包含大約100.000個元素的數組。將數組與一個「非常大」的SQL Server數據庫表進行比較
然後,我有一個SQL Server 2008表,其中主鍵列包含或多或少幾乎所有的數組元素(但有一些不是)。該表最多可以有30,000.000行。
現在我想確定數組中哪些元素不存在於表中。如何有效實現這一點?
最有效的方法可能是將這些100,000個元素批量插入臨時表中,然後在數據庫中執行比較。
(請注意,我沒有測試這個理論,它只是一個猜測。)
查詢表與
select <primarykey> where <primarykey> in (<primary key of ur list of elements in c#>)
這應該是不是插入的所有行插入表更快然後檢查丟失元素的except/minus命令,因爲它不涉及任何寫入操作。
一旦你有主鍵的列表是common.pull它回到c#和比較。
避免創建臨時表的一種方法是使用接受用戶定義表類型(udtt)的表值參數的存儲過程。這個表格將有一個數據類型的一列與您的數組中匹配的模式。
如果使用數組值填充DataTable(使用與udtt模式匹配的模式)並將數據表作爲存儲過程的參數提供,那麼可以將所有100,000個項目以sql二進制格式傳遞。 proc可以在30M行表和表值參數之間進行連接,返回TVP表中沒有匹配的表中的項目。
這避免了需要構建大量的IN
語句。
編輯關於從@Kyro下面
我現在在這種方法缺乏自信的評論。我發現an article顯示了Kyro描述的行內插入內容。在通過網絡發送二進制數據而不是大型TSQL where in()
聲明中,您可能會獲得什麼,可能會被性能SQL方面帶走。然而,這是一個相當簡單的代碼方法,所以可能只是值得快速測試。讓我們知道您的身體情況如何?
這是理論上最好的答案,雖然我發現TVPs在實踐中的速度令人難以置信。 OP應當確定不同的建議方法的基準,並確定哪一個最適合他們以及他們的特定設置。 – LukeH
實際上,對於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
@LukeH - 我們發現在查詢結尾處有一個OPTION(RECOMPILE)語句可以幫助解決性能問題。這是因爲TVP沒有統計數據,所以SQL假定TVP爲了查詢優化而保持一行。 RECOMPILE生成了一個更好的計劃,並將執行時間從幾分鐘縮短到幾秒鐘。 –
所有的本地身份證是完全隨機的,還是它們發生在相對體面的連續羣體中? – MatBailie