2013-07-26 47 views
3

在我的項目中,我使用實體框架4.4.0.0,我有以下困境。我必須檢查用戶是否被激活。我的查詢是這樣的:在實體框架中比較Any()和Count Count()生成的查詢的性能5

任何()

_context.Users.Any(u => u.Id == userId && u.IsActivated); 

生成的SQL是:

SELECT CASE 
     WHEN (EXISTS (SELECT 1 AS [C1] 
         FROM [dbo].[Users] AS [Extent1] 
         WHERE ([Extent1].[Id] = @p__linq__0) 
           AND ([Extent1].[IsActivated] = 1))) THEN cast(1 AS BIT) 
     WHEN (NOT EXISTS (SELECT 1 AS [C1] 
          FROM [dbo].[Users] AS [Extent2] 
          WHERE ([Extent2].[Id] = @p__linq__0) 
           AND ([Extent2].[IsActivated] = 1))) THEN cast(0 AS BIT) 
     END AS [C1] 
FROM (SELECT 1 AS X) AS [SingleRowTable1] 

對於Count()我這樣的語句:

SELECT [GroupBy1].[A1] AS [C1] 
FROM (SELECT COUNT(1) AS [A1] 
     FROM [dbo].[Users] AS [Extent1] 
     WHERE ([Extent1].[Id] = @p__linq__0) 
       AND ([Extent1].[IsActivated] = 1)) AS [GroupBy1] 

這是否看起來正確?我不像sql那麼好......但對我來說看起來效率不高。我錯過了什麼嗎?

是 'select count(*) from dbo.Users where [email protected] and IsActivated=1' 效率不高?

+0

第一個看上去效率低,但要記住,一個'EXISTS'將盡快匹配的記錄中發現停止。我對它的唯一問題是在第二個「WHEN」中重複查詢。我會期待它使用'ELSE cast(0 as bit)'。但是,查詢優化器應該只執行一次該查詢。 – cadrell0

+0

@ cadrell0 - 優化器不僅會執行一次。參見[爲聚結不必要糟糕的表現(子查詢)](http://connect.microsoft.com/SQLServer/feedback/details/336002/unnecessarily-bad-performance-for-coalesce-subquery) –

+0

@MartinSmith不說,優化器的一點? – cadrell0

回答

5

這取決於。

EXISTS實現不是很大無論是。如果有0行,它將執行兩次檢查。在這種情況下,COUNT會更好,因爲它只需要搜索不存在的行並計算一次。

您可能會發現,檢查

_context.Users 
     .Where(u => u.Id == userId && u.IsActivated) 
     .Select(u=> true) 
     .FirstOrDefault(); 

給出比兩個更好的計劃(修訂如下盧克的建議)。測試上EF4查詢生成是沿

SELECT TOP (1) cast(1 AS BIT) AS [C1] 
FROM Users 
WHERE userId = @userId 
     AND IsActivated = 1 

含義它不處理不必要的額外行,如果多於一個的存在,並且僅執行用於匹配WHERE一次行的搜索線。

+1

我同意這會更快根據你所說的存在,是在那裏選擇避免下載整行?那麼'.Select(u => true).FirstOrDefault()'(默認爲bool = false,例如no rows => false) –

+0

@LukeMcGregor - 是的,我認爲這樣會更好。不依賴於選擇不可空列和更好的方式直接返回布爾值,而不必執行'== null'檢查。生成的查詢是'SELECT TOP(1)cast(1 as bit)AS [C1] FROM .... WHERE' –

+0

另外,我有一些關於任何EF源的看看,我認爲它的方式是爲了可以在更大的表達式的子查詢中使用它,我不太確定如果它處於更大的數據庫查詢的中間,那麼寫入該數據的更好方法是存在的。 (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework.SqlServer/SqlGen/SqlGenerator.cs搜索'result.Append(「EXISTS(」);') –

3

是的。 當您執行計數時,您將選擇與您的子句匹配並計數的所有條目。使用Any(),您的查詢將返回符合條款的註冊表的第一個符號。 我是我的opnion它總是更好地使用任何()比count(),除非當你真的需要這個數字

相關問題