Any vs FirstOrDefault的性能

时间:2013-01-28 14:36:58

标签: sql-server entity-framework

所以我一直在挖掘EF为我们的应用程序生成的查询,我注意到一些奇怪的SQL生成Any调用 - 它们似乎过于复杂。 Any似乎生成case when (x) then 1 when (not x) then 0 end - 为什么不只使用其他?这样,在Any应返回false的情况下,SQL Server必须执行两次相同的查询。我想出了在使用Where(cond).Select(q => true).FirstOrDefault()的情况下似乎更快的解决方法,但我仍然对这是否只是疏忽感兴趣,或者它有一些我缺失的含义。

context.Books.Any(b => b.Id == bookId);

declare @p__linq__0 Int = 1;

SELECT 
CASE WHEN ( EXISTS (SELECT 
    1 AS [C1]
    FROM [Books] AS [Extent1]
    WHERE [Extent1].[ID] = @p__linq__0
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT 
    1 AS [C1]
    FROM [Books] AS [Extent2]
    WHERE [Extent2].[ID] = @p__linq__0
)) THEN cast(0 as bit) END AS [C1]
FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]

context.Books.Where(b => b.ID == bookId).Select(b => true).FirstOrDefault();

declare @p__linq__0 Int = 1;

SELECT TOP (1) 
cast(1 as bit) AS [C1]
FROM [Books] AS [Extent1]
WHERE [Extent1].[ID] = @p__linq__0

1 个答案:

答案 0 :(得分:1)

在你看到某些东西不存在之后很明显它确实不存在,所以检查agin是否真的不存在是没有必要的。这只是linq生成过于复杂的查询的案例之一。你的解决方法是有效的,但它并不像人们想的那样容易理解,所以我建议采用原始linq的性能命中,直到它真正成为性能问题。只需确保Id列上有索引。