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行.
(点击查看大图)
这是由于在结合使用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
因为这会使结果的顺序不确定.