实体框架 - 如何优化“包含”语句?

时间:2014-11-06 13:55:55

标签: c# sql-server-2008-r2 entity-framework-4

在我们当前的应用程序中,我们的一些查询存在一些性能问题。通常我们有类似的东西:

List<int> idList = some data here…;
var query = (from a in someTable where idList.Contains(a.Id));

虽然对于简单查询这是可以接受的,当我们在idList中有更多项时它会成为瓶颈(例如,在某些查询中我们有大约700个id要检查)。

有没有办法使用其他包含的东西?我们正在考虑使用一些临时表来首先插入Ids,然后执行join而不是Contains,但看起来EntityFramework似乎不支持这样的操作(在代码中创建临时表):(

我们还能尝试什么?

5 个答案:

答案 0 :(得分:1)

我建议使用LINQ PAD它提供了一个“转换为SQL”选项,允许您以SQL语法查看查询。

这可能是最佳解决方案(如果你没有陷入混乱的东西)。 可能会尝试将idList保存为已排序的数组,并将contains方法替换为二进制搜索。 (您可以实现自己的扩展名。)

答案 1 :(得分:1)

如果您不介意使用物理表,则可以使用半临时表。基本思路是:

  1. 使用“查询ID”列
  2. 创建物理表
  3. 生成唯一ID(不是随机,但唯一
  4. 将数据插入到表中,并使用查询ID
  5. 标记记录
  6. 将查询ID传递给主查询,使用它来加入链接表
  7. 查询完成后,删除临时记录
  8. 最糟糕的是,如果出现问题,您将在链接表中显示孤立记录(这就是您使用唯一查询ID的原因)。

    这不是最干净的解决方案,但如果您需要检查很多值,它将比使用Contains更快。

答案 2 :(得分:1)

当Entity Framework开始成为性能瓶颈时,通常是时候编写实际的SQL了。

因此,您可以做的是构建一个table-valued function,它将表值参数(您的ID列表)作为参数。该函数只会返回JOIN的结果。

表值函数功能需要EF5,因此如果你真的坚持使用EF4,它可能不是一个选项。

答案 3 :(得分:0)

你可以试试这个:

var query = someTable.Where(a => idList.Any(b => b.Id == a.Id));

答案 4 :(得分:0)

我们的想法是重构您的查询以摆脱idList

例如,您应该从法国返回18-25岁男性用户的订单列表。如果您按年龄,性别和国家/地区过滤用户表格以获得idList个用户,则最终会获得700个以上的ID。而是将Orders表连接到Users并将过滤器应用于Users表。因此,您没有2个请求(一个用于ID,一个用于订单)并且它的工作速度要快得多,因为它可以在加入表时使用索引。

有道理吗?