【发布时间】:2014-05-07 13:05:04
【问题描述】:
我有一个非常简单的查询,非常慢。 Entity Framework Profiler 表示大约需要 100 毫秒。
dbContext.Users.Single(u => u.Id == userId);
经过一番尝试,我发现了一个非常相似但速度更快(大约 3 毫秒)的查询。
dbContext.Users.Where(u => u.Id == userId).ToList().Single();
当我比较两个查询的 sql 时,第二个查询不使用嵌套的 SELECT 并且没有 TOP 操作。但我不希望它仅仅因为这两件事而快 30 倍。此外,当使用 SQL Server Management Studio 执行查询时,没有可测量的差异。
当我查看执行计划时,它们都进行了聚集索引查找,查询成本为 100%。而额外的 select 和 Top 操作的查询成本为 0%。 来自 EFProfiler 的查询计划表示相同,表明它不应该有任何区别。
如何才能更好地了解这种情况下的查询性能?
下面是第一个查询的结果 SQL。
SELECT [Limit1].[Id] AS [Id],
[Limit1].[EmailAddress] AS [EmailAddress],
[Limit1].[FirstName] AS [FirstName],
[Limit1].[LastName] AS [LastName]
FROM (SELECT TOP (2) [Extent1].[Id] AS [Id],
[Extent1].[EmailAddress] AS [EmailAddress],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName]
FROM [dbo].[Users] AS [Extent1]
WHERE ([Extent1].[Id] = 'b5604f88-3e18-42a5-a45e-c66cc2a632d3' /* @p__linq__0 */)
AND ('b5604f88-3e18-42a5-a45e-c66cc2a632d3' /* @p__linq__0 */ IS NOT NULL)) AS [Limit1]
这里是第二个(更快)查询的 sql。
SELECT [Extent1].[Id] AS [Id],
[Extent1].[EmailAddress] AS [EmailAddress],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName]
FROM [dbo].[Users] AS [Extent1]
WHERE ([Extent1].[Id] = 'b5604f88-3e18-42a5-a45e-c66cc2a632d3' /* @p__linq__0 */)
AND ('b5604f88-3e18-42a5-a45e-c66cc2a632d3' /* @p__linq__0 */ IS NOT NULL)
【问题讨论】:
-
您也可以在第二个示例中省略
ToList()调用。Single()还枚举查询。只需保留Where()子句即可。 -
.Single() 需要返回的“top 2”结果来确定是否存在单个匹配项。结果中的一行表示成功,两行或零行表示“.Single()”失败并且应该抛出错误。在您的第二个示例中,“.ToList()”导致查询在应用“.Single()”之前执行。查询可以返回任意数量的结果,.Single() 方法将应用于 List 结果。
-
您是否在同一个应用程序中尝试这两个查询,如果是这样,是实体框架在您的应用程序中进行的第一个查询中的两个中较慢的吗?实体框架对于每个应用程序域的每个数据库执行的第一个查询来说是一个非常重要的开销,即使对象被释放,它也会重用它在第一个查询之后构建的缓存元数据,但是第一个查询将会很多较慢(稍后在程序中第二次运行相同的查询,您将看到速度显着变化)
-
@Towa 我很惊讶 GUID 上的聚集索引并没有降低性能
-
@Jaycee:很可能是这样,但也可能是他的表很小,所以如果有的话,它的分页并不多……GUID 会造成错误的主键……
标签: sql sql-server performance entity-framework database-performance