繁体   English   中英

Linq2Sql 通过多个 id 选择记录?

[英]Linq2Sql select records by multiple ids?

例如,我有一个包含 10000000 条记录的表,并在内存中列出了 100000 个 ID。

如何通过这些 id 选择所有记录? 显然,我可以这样做:

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

但是如果我这样做的话,就会有两个问题:

  • 每次我使用这个查询时,生成的 SQL 都会出现异常。

  • 每行的复杂度为 O(N)。 所以,我将在几年内收到我的结果。

我怎么能做到这一点? 这是如何用linq2sql完成的,或者这是不可能绕过的?


更新

  • GetIds - 此函数返回大约 100.000 个 ID。 不,我不能加入它。 它是计算出来的
  • 是的,我测试了它,我调试了它并看到了生成的内容。 它是这样的:

     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。 这是非常低效的。

正如您所说,在内存中执行这些操作并不好。 解决方案是在您的数据库中有另一个表,然后您的代码将是:

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列: IdOperationId 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;

_确保OperationId被索引 - 可以是Id的相同索引,但请注意它是按顺序排列的第一个。


根据 DBMS,您还可以将您的表作为temporary table - 至少对于 Oracle 而言,它存储每个连接会话的数据 - 因此您可以一次从多个会话插入,但数据不共享 - 所以您不会需要OperationId

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM