为什么我的实体框架查询单慢?

Kue*_*per 6 sql sql-server performance entity-framework database-performance

我有一个非常简单的查询非常慢.Entity Framework Profiler表示大约需要100毫秒.

dbContext.Users.Single(u => u.Id == userId);
Run Code Online (Sandbox Code Playgroud)

尝试了一下后,我发现了一个非常相似但速度更快的查询(大约3毫秒).

dbContext.Users.Where(u => u.Id == userId).ToList().Single();
Run Code Online (Sandbox Code Playgroud)

当我比较两个查询的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]
Run Code Online (Sandbox Code Playgroud)

这里是第二个(更快)查询的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)
Run Code Online (Sandbox Code Playgroud)

Ans*_*gam 0

当你说

dbContext.Users.Single(u => u.Id == userId);

Users 是 DbSet 类型或其用户集合,因此它首先获取用户集合,同时其中
dbContext.Users.Where(u => u.Id == userId).ToList().Single(); 包含加载它的条件。

因此,如果有 100 个用户,第一个查询将获取 100 个用户,然后进行过滤,而第二个查询将仅获取 1 个用户。

希望这可以帮助。

  • Anshul,第一个查询将仅返回数据库中与该用户 ID 匹配的前两个用户。它不会获取所有 100 个用户。即使有 100 个用户具有该用户 ID。第二个将返回与该用户 ID 匹配的所有用户,然后在内存中将应用单一方法。 (3认同)