2015-04-24 15 views
5

Próbuję zrozumieć, dlaczego dołączam do mojej skrzynki szybciej niż instrukcja, która korzysta z właściwości nawigacji. Mam dwa zapytania.Entity framework performance join vs navigation property

Pierwszy z własności nawigacja:

  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 

drugie z przyłączyć:

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(); 

Generated 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]) 

Przed uruchomieniem pierwszego zapytania zadzwoń pod numer var user = context.User.FirstOrDefault();, ponieważ wydaje mi się, że otwarte połączenie z bazą danych zajmuje trochę czasu.

Wyniki: Nawigacja zapytań nieruchomości: 00: 00: +00,6719646 Dołącz zapytanie: 00: 00: 00,4941169

Patrząc na wyniki wydaje się, że stosowanie zapytań LINQ dołącza zamiast właściwości nawigacyjnych są szybsze. Czy to prawda, czy robię coś nie tak?

+0

Musisz również wyczyścić pamięć podręczną z bazy danych pomiędzy zapytaniami, aby uzyskać prawidłowe wyniki, gdy wywołujesz funkcję ToList(). Oddziel konstrukcję zapytania od materializacji i porównuj ją. –

+0

OrderBy nie wydaje się być brany pod uwagę w drugim zapytaniu. Może to być przyczyną różnicy, Możesz spróbować '... od s w kolejności użytkowników przez u.LastName, u.FirstName ...' – jbl

Odpowiedz

2

Aby uzyskać lepszy wgląd w to, co robi, powinieneś uzyskać surowy SQL i możesz sam sprawdzić plan wykonania.

Aby to zrobić, można użyć SQL Profiler, aby zobaczyć co kwerenda jest uruchomiony, czy można zalogować zapytanie SQL sam robiąc coś takiego przed uruchomieniem zapytanie:

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

robi także prosty test porównawczy, który wykonujesz, uruchamiając każdy z nich, niekoniecznie musi być wiarygodny. Będziesz chciał uruchomić go wiele razy i wyliczyć. Powinieneś również uruchomić je w odwrotnej kolejności, aby sprawdzić, czy to również zmieni sytuację.

+0

Ponadto wstawianie większej ilości danych do bazy danych jest dobrym pomysłem, powinno to podkreślać różnicę (jeśli istnieje) –

+0

oba zapytania zwrócone ponad 9000 wierszy ... i tak używam dziennika i uruchamiam kwerendy z nową instancją kontekstu mojej bazy danych. Dołącz nadal jest szybszy. – puko

+0

Czy możesz umieścić SQL, który jest uruchamiany w oryginalnym pytaniu? Czy uruchomiłeś SQL w SSMS i włączył plan wykonania, aby zobaczyć, gdzie są różnice? –