2016-10-12 175 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