我正在开发一个使用Entity Framework的MVC网站。我是一个前ADO.Net形式的人,所以这对我来说有点新鲜。我的EDM目前由一个抽象的“产品”实体组成,它有5个不同的“类型”实体,从中继承。 “产品”实体映射到7或8个表并具有约50个属性,每个“类型”继承自“产品”具有约5到20个额外属性,这些属性扩展了“产品”。我注意到当我在IQueryable上使用.Take扩展方法将数据返回到Telerik网格时,返回数据的时间明显长于使用.ToList贪婪地将整个集合返回到内存。
当我运行SQL事件探查器以查看恶魔正在发生的事情时,我发现了这一点。
exec sp_executesql N'SELECT TOP (20)
[Project12].[C1] AS [C1],
[Project12].[C2] AS [C2],
[Project12].[C3] AS [C3],
etc ... 508 SQL lines follow, too much to paste here unfortunately.
执行需要500毫秒。以下是:
exec sp_executesql N'SELECT
[Project12].[C1] AS [C1],
[Project12].[C2] AS [C2],
[Project12].[C3] AS [C3],
etc ...
大约需要80毫秒才能执行。
因此,根据上述逻辑判断,我应该放弃延迟执行,每次用户更改页面时......将整个数据集放入内存(500行左右)。有没有人有任何建议,以及SQL Server 2005以这种方式表现的原因?
修改
我已将完整的SQL放在http://pastebin.com/rAGGSScA上。可能是SQL正在缓存“完整”选择,而不是缓存“TOP(20)”结果?
SELECT的客户端统计信息
SELECT TOP(20)的客户端统计信息
答案 0 :(得分:1)
在你的“508 SQL行[后面跟随”中的某个地方将是一个ORDER BY子句。通过强制对查询进行“TOP(N)”评估,您迫使服务器更早地评估此order by子句,并在之前计算所有结果(包括其顺序)任何都可以显示。您可能最终会得到完全不同的执行计划,甚至可能使索引无效(或者与不太理想的索引相匹配)。如果没有“TOP(n)”子句,服务器可以在知道将使用记录后立即开始显示结果。
答案 1 :(得分:1)
如果他们都有一个ORDER BY
,那么我的猜测是慢的是使用不太普遍有效的不同计划,但是以所需的排序顺序输出行,快速计划使用不同的计划以非排序顺序输出行,并具有明确的SORT
步骤。
可能的情况是,当使用较慢的计划时,SQL Server需要处理超过20行以获得TOP 20
输出(因为许多通过连接或where子句标准消除)并且它没有正确地估计这个因素导致它错误地将慢速计划花费比快速计划更便宜。