EF分选&分页 - 两次订购速度慢?

时间:2014-06-24 10:08:36

标签: c# entity-framework entity-framework-6

我有一个简单的实体,我的SQL Sever 2012数据库中有100,000个实体:

public class Entity
{
    public int Id { get; set; }
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

我想在网格中显示这些内容,分页为100,000,太多而无法在一个屏幕上显示(并且效率不高)。网格应该允许排序和过滤 - 显然所有这些操作中的3个最好在服务器上完成,EF应该翻译它们。

所以,让我们得到按Field1排序的第二页500:

var items = context.Entities.OrderBy(e => e.Field1).Skip(500).Take(500);

执行此查询时, 12秒!所以我挖了它,发现它的翻译如下:

SELECT TOP (500) [Extent1].[Id]     AS [Id],
                 [Extent1].[Field1] AS [Field1],
                 [Extent1].[Field2] AS [Field2]               
FROM   (SELECT [Extent1].[Id]     AS [Id],
               [Extent1].[Field1] AS [Field1],
               [Extent1].[Field2] AS [Field2],
               row_number() OVER (ORDER BY [Extent1].[Field1] ASC) AS [row_number]
        FROM   [dbo].[Costs] AS [Extent1]) AS [Extent1]
WHERE  [Extent1].[row_number] > 500
ORDER  BY [Extent1].[Field1] ASC        

当然这是两次排序?我没有SQL专家,但是子查询按Field1排序并将此顺序分配给row_number。然后我们将TOP 500的row_numbers超过500以获得最多500行的第2页。我们不需要再次按Field1订购结果。

如果我拿出最后的ORDER BY [Extent1].[Field1] ASC,查询结果似乎相同,执行时间下降到大约150毫秒。

所以,显然150毫秒优于12秒 - 有什么我做错了吗?我能做些什么来解决这个问题吗?

更新

两者的查询计划相同。排序工具提示的唯一区别是“实际行数”和#39; 12s查询为4,604,150ms查询为1,134。我想补充一点,这是从15个单词的固定列表中生成的数据(对于此测试) - 即Field1包含15个值中的1个,因此基本上有15个组,每组6,666行。

Query Plan

click for larger image

SQL Server 2012 backup

2 个答案:

答案 0 :(得分:6)

这是由于当TOP和Gather Streams组合在一起时SQL Server中的错误/特性。 索引将修复它,同样会禁用并行性(全局,或此用户或查询)。线索是Gather Streams溢出到tempdb,这是一种非常罕见的情况。 http://web.archive.org/web/20180220120719/http://sqlblog.com:80/blogs/paul_white/archive/2012/05/03/parallel-row-goals-gone-rogue.aspx这是500级别的东西。

请注意,您不能忽略最终ORDER BY,因为这会导致结果的顺序未定义。

答案 1 :(得分:1)

我认为您的问题是因为在大型未编入索引列上执行了订单。

请确保您为该列编制索引。

无论如何,order by子句会更好,而不是nvarchar