[英]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
完成的,或者这是不可能绕过的?
更新
是的,我测试了它,我调试了它并看到了生成的内容。 它是这样的:
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
子句中项目数量的限制。
Records
的id
字段应该有一个索引(或者如果它是一个主键,它也已经被索引了)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;
_确保OperationId
被索引 - 可以是Id
的相同索引,但请注意它是按顺序排列的第一个。
根据 DBMS,您还可以将您的表作为temporary table
- 至少对于 Oracle 而言,它存储每个连接会话的数据 - 因此您可以一次从多个会话插入,但数据不共享 - 所以您不会需要OperationId
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.