Linq to实体使用.Take()方法非常慢

时间:2012-12-18 13:37:20

标签: c# asp.net linq entity-framework

我有一张200,000条记录的表格,我只使用.Take()获得前10名,但获取数据大约需要10秒钟。

我的问题是:.Take()方法是否从数据库获取所有数据并过滤客户端的前10位?

这是我的代码:

mylist = (from mytable in db.spdata().OrderByDescending(f => f.Weight)
                                    group feed by mytable.id into g
                                    select g.FirstOrDefault()).Take(10).ToList();

spdata()是从存储过程导入的函数。

由于

4 个答案:

答案 0 :(得分:8)

存储过程可能会向客户端返回大量数据,这非常慢。您无法远程查询sproc。这可以使用视图或表值函数。

在查询中无法使用sproc。你只能自己执行它。

您的意图可能是在服务器上执行Take(10)。为此,您需要切换到内联查询,视图或TVF。

答案 1 :(得分:6)

扩展方法Take 从数据库中获取所有结果。这不是Take的工作方式。

但是,您的db.spdata()调用可能会获取所有行。

答案 2 :(得分:1)

我不是百分百肯定但是我记得当你使用EF DataContext调用SP时会得到一个IEnumerable结果......

有一些是优化性能:

  • 将搜索条件s作为SP参数传递,并在存储过程中进行过滤。

或者,如果您在SP中有一个非常简单的查询,您没有声明任何变量,而您只是加入某些表,那么:

  • 创建一个索引视图,在其中指定所需的查询并在其上调用Take方法。
    这会给你什么?您可以映射到创建的视图,EF现在将返回IQueryable结果而不是IEnumerable。这将优化sql命令,而不是接收所有数据,然后获取所需的10个元素,将形成一个只检索10个元素的sql命令。

我还建议你看看IEnumerable和IQueryable之间的差异是什么。

答案 3 :(得分:0)

确实如此,因为您在分组之前对数据进行排序,这在SQL中是不可能的。

您应该使用聚合来从每个组中获得最高权重,然后对权重进行排序以获得最大权重:

mylist = (
  from mytable in db.spdata()
  group feed by mytable.id into g
  select g.Max(f => f.Weight)
).OrderByDescending(w => w).Take(10).ToList();