EF排序和分页 - 两次订购速度慢?

Cha*_*ger 1 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; }
}
Run Code Online (Sandbox Code Playgroud)

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

所以,让我们按字段1排序第二页500:

var items = context.Entities.OrderBy(e => e.Field1).Skip(500).Take(500);
Run Code Online (Sandbox Code Playgroud)

执行此查询时,需要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        
Run Code Online (Sandbox Code Playgroud)

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

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

所以,显然150ms优于12s - 有什么我做错了吗?有什么办法可以解决这个问题吗?

更新

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

查询计划

(点击查看大图)

SQL Server 2012备份

usr*_*usr 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因为这会使结果的顺序不确定.