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

标签 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 以获得第 2 页最多 500 行。我们不需要再次按 Field1 对结果进行排序。

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

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

更新

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

Query Plan

( click for larger image )

SQL Server 2012 backup

最佳答案

这是由于 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,因为这会使结果的顺序不确定。

关于c# - EF 排序和分页 - 两次订购速度慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24383874/

相关文章:

mysql - HistoryRow 没有键

c# - Azure 上的 EF6 连接到远程 MySQL DB 时出现间歇性问题

c# - Automapper 4.2.1 LINQ 投影仅适用于静态 Mapper.CreateMap?

mysql - 创建对象时减少对数据库的调用次数?

c# - 可空类型和赋值运算符

c# - c=C# 中是否可以使用多个迭代器?

c# - Fluentvalidation WithMessage 和单例实例

c# - Entity Framework 中的反向属性和外键有什么区别?

c# - Entity Framework 的悲观并发

c# - Generic SortedList,如何找到大于搜索键的第一个元素的索引?