2016-10-12 177 views
1

例如,我有10000000條記錄的表格,並在內存中列出了,其中有100000個ID。Linq2Sql通過多個ID選擇記錄?

如何通過這些ID選擇所有記錄? 很顯然,我可以做這樣的:

var ids = GetIds(); 
var result = from q in ctx.Records 
      where ids.Contains(q.Id) 
      select q; 

但是,如果我不喜歡這樣,就會有兩個問題:

  • 畸形率在生成的SQL每次使用此查詢時間。

  • O(N)complexety爲每一行。所以,我會在幾年後收到我的結果。

我該怎麼做?這是怎麼做到的linq2sql或者這是不可能繞過?


更新

  • GetIds - 該函數返回約100.000 IDS。不,我不能加入它。 這是計算
  • 是的,我測試了它,我調試了它,看到了什麼產生。這是這樣的:

    SELECT * FROM Records WHERE id IN (/*one hundreds of thousand goes here O_O*/) 
    

    簡單的數學:10.000.000 x 100.000會給時間複雜性1.000.000.000.000。這是非常沒有效率的。

+0

什麼讓你覺得它是每個行的O(N)? – Andrey

+0

什麼是GetIds?這是從哪裏來的,返回類型是什麼? –

+1

你測試過它很慢嗎?它將被翻譯成'WHERE ID IN(1,2,3,4,5,...,100000)'查詢。當然,這不是最好的方法(因此您可以使用用戶定義的表類型和表值參數,但不再使用LINQ-to-SQL)。 –

回答

1

正如你所說的在內存中執行這些操作並不好。解決的辦法是有另一個表中您的數據庫,然後你的代碼將是:

var ids = GetIds(); 
//Insert all ids into database (bulk insert) 

var result = from q in ctx.Records 
      join i in ctx.Ids on q.Id equals i.Id 
      select q; 

這樣的操作將在數據庫中,你會克服的項目數量的限制在in條款。

  1. Recordsid場應該有一個索引(或者如果它是一個主鍵,它已經也被編入索引)
  2. Ids表的id字段也應該被索引

這樣,加入將是Hash join而不是Nested Join-等效於使用ids集合作爲HashSet<string>而不是List<string>的.Net解決方案。

最後,爲了支持許多並行操作,您可以在Ids上使用2列:Id,OperationId。該OperationId將給予所有Id個特定的插入,然後你的查詢看起來像:

var result = from q in ctx.Records 
      join i in ctx.Ids on q.Id equals i.Id 
      where i.OperationId = _the operationId given by the insert_ 
      select q; 

_make確保OperationId被索引過 - 可以是Id同一指數,但看到它是第一個按順序。


根據DBMS你也可以有你的表爲temporary table - 其中至少對Oracle存儲它每連接會話的數據 - 這樣你就可以從多個會話一次插入但數據不共享 - 所以你不需要OperationId

-2

,如果你的IDS是固定的,創建單列臨時表中,ID添加到它,然後使用連接來獲得行

+1

因爲很重要,它不是一個Linq2Sql問題,儘管問題標題... – code4life

+0

請刪除投票,因爲正確答案與我的相同 – ammcom