在我们当前的应用程序中,我们的一些查询存在一些性能问题。通常我们有类似的东西:
List<int> idList = some data here…;
var query = (from a in someTable where idList.Contains(a.Id));
虽然对于简单查询这是可以接受的,当我们在idList中有更多项时它会成为瓶颈(例如,在某些查询中我们有大约700个id要检查)。
有没有办法使用其他包含的东西?我们正在考虑使用一些临时表来首先插入Ids,然后执行join而不是Contains,但看起来EntityFramework似乎不支持这样的操作(在代码中创建临时表):(
我们还能尝试什么?
答案 0 :(得分:1)
我建议使用LINQ PAD它提供了一个“转换为SQL”选项,允许您以SQL语法查看查询。
这可能是最佳解决方案(如果你没有陷入混乱的东西)。 可能会尝试将idList保存为已排序的数组,并将contains方法替换为二进制搜索。 (您可以实现自己的扩展名。)
答案 1 :(得分:1)
如果您不介意使用物理表,则可以使用半临时表。基本思路是:
最糟糕的是,如果出现问题,您将在链接表中显示孤立记录(这就是您使用唯一查询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,一个用于订单)并且它的工作速度要快得多,因为它可以在加入表时使用索引。
有道理吗?