2015-04-24 128 views
5

我想了解爲什麼加入我的情況比使用導航屬性的語句更快。我有兩個疑問。實體框架性能連接與導航屬性

先用導航屬性:

  var result = (from users in context.MetricBloodPreasure 
       orderby users.User.LastName, users.User.FirstName 
       select new 
       { 
        UserName = users.User.LastName + ", " + users.User.FirstName, 
        Date = users.DateOfValue, 
       }).ToList(); 

Generatet SQL:

SELECT 
    [Project1].[C1] AS [C1], 
    [Project1].[C2] AS [C2], 
    [Project1].[DateOfValue] AS [DateOfValue] 
    FROM (SELECT 
     [Extent1].[DateOfValue] AS [DateOfValue], 
     [Extent2].[FirstName] AS [FirstName], 
     [Extent2].[LastName] AS [LastName], 
     1 AS [C1], 
     CASE WHEN ([Extent2].[LastName] IS NULL) THEN N'' ELSE [Extent2].[LastName] END + N', ' + CASE WHEN ([Extent2].[FirstName] IS NULL) THEN N'' ELSE [Extent2].[FirstName] END AS [C2] 
     FROM [dbo].[MetricBloodPreasure] AS [Extent1] 
     INNER JOIN [dbo].[User] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id] 
    ) AS [Project1] 
    ORDER BY [Project1].[LastName] ASC, [Project1].[FirstName] ASC 

第二位加盟:

var result1 = (from u in context.User 
       orderby u.LastName, u.FirstName 
       join us in context.MetricBloodPreasure 
        on u.Id equals us.UserId into users 
       from s in users 
       select new 
       { 
        UserName = s.User.LastName + ", " + s.User.FirstName, 
        Date = s.DateOfValue, 
       }).ToList(); 

生成的SQL:

SELECT 
    1 AS [C1], 
    CASE WHEN ([Extent1].[LastName] IS NULL) THEN N'' ELSE [Extent1].[LastName] END + N', ' + CASE WHEN ([Extent1].[FirstName] IS NULL) THEN N'' ELSE [Extent1].[FirstName] END AS [C2], 
    [Extent2].[DateOfValue] AS [DateOfValue] 
    FROM [dbo].[User] AS [Extent1] 
    INNER JOIN [dbo].[MetricBloodPreasure] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[UserId]) AND ([Extent2].[UserId] = [Extent1].[Id]) 

在運行第一個查詢之前,請撥打var user = context.User.FirstOrDefault();,因爲我認爲與數據庫的開放連接需要一些時間。

結果: 導航屬性查詢:00:00:00.6719646 加入查詢:00:00:00.4941169

看結果似乎LINQ查詢在使用連接,而不是導航性能更快。這是真的還是我做錯了什麼?

+0

您還需要在查詢之間清除數據庫中的緩存,以便在調用ToList()時獲得正確的結果。將查詢結構從實現中分離出來並進行基準測試。 –

+0

OrderBy在第二個查詢中似乎沒有考慮到。這可能是導致差異的原因,你可以嘗試'...從用戶的命令u.LastName,u.FirstName ...' – jbl

回答

2

爲了更好地瞭解它在做什麼,您應該獲得原始SQL,並且您可以自己查看執行計劃。

要做到這一點,您可以使用SQL事件探查器,看看有什麼查詢正在運行,也可以通過做這樣的事情在運行查詢之前登錄的SQL查詢本身:

context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s); 

也做的一個簡單的基準就像你每次運行一樣,不一定是可靠的。你會想多次運行它,並平均事情。你也應該按照相反的順序來運行它們,看看它是否也會改變。

+0

此外插入更多的數據到數據庫是好主意,這應該突出顯示差異(如果存在) –

+0

這兩個查詢都返回了超過9000行...是的,我使用日誌並運行我的數據庫上下文的新實例的查詢。加入仍然更快。 – puko

+0

你可以發佈正在運行的SQL到原始問題嗎?另外,你有沒有在SSMS中運行SQL並打開執行計劃,以便你能看到差異在哪裏? –