2016-08-26 13 views
7

Po aktualizacji do Asp.Net Core 2015.1 zauważyłem, że wiele zapytań EF stało się o wiele wolniej uruchamianych.Czy ktoś zauważył, że EF Core 1.0 2015.1 sprawił, że zapytania były bardzo nieefektywne?

Zrobiłem pewne dochodzenie i odkryłem, że wiele zapytań, gdzie filtry są teraz oceniane w Kodzie, zamiast przekazywać filtry do SQL jako część klauzuli where, aby uruchomić z zapytaniem.

W efekcie musieliśmy ponownie zapisać kilka naszych zapytań jako procedury przechowywane, aby odzyskać wydajność. Zauważ, że były one wydajne przed wersją 2015.1. Coś oczywiście zostało zmienione, a wiele zapytań robi wybranie wszystkich zapytań w tabeli, a następnie filtrowanie danych w kodzie. Takie podejście jest straszne dla wydajności, np. czytanie tabeli z dużą ilością wierszy, aby filtrować wszystko, ale może 2 wiersze.

Muszę zapytać, co się zmieniło i czy ktoś jeszcze widzi to samo?

Na przykład: Mam ForeignExchange stół wraz z ForeignExchangeRate tabeli, które są połączone poprzez ForeignExchangeid = ForeignExchangeRate.ForeignExchangeId

await _context.ForeignExchanges 
       .Include(x => x.ForeignExchangeRates) 
       .Select(x => new ForeignExchangeViewModel 
       { 
        Id = x.Id, 
        Code = x.Code, 
        Name = x.Name, 
        Symbol = x.Symbol, 
        CountryId = x.CountryId, 
        CurrentExchangeRate = x.ForeignExchangeRates 
         .FirstOrDefault(y => (DateTime.Today >= y.ValidFrom) 
              && (y.ValidTo == null || y.ValidTo >= DateTime.Today)).ExchangeRate.ToFxRate(), 
        HistoricalExchangeRates = x.ForeignExchangeRates 
         .OrderByDescending(y => y.ValidFrom) 
         .Select(y => new FxRate 
         { 
          ValidFrom = y.ValidFrom, 
          ValidTo = y.ValidTo, 
          ExchangeRate = y.ExchangeRate.ToFxRate(), 
         }).ToList() 

       }) 
       .FirstOrDefaultAsync(x => x.Id == id); 

I to wykorzystać, aby uzyskać dane do edycji kursu zagranicznego

Więc SQL wygenerowany nie jest zgodny z oczekiwaniami. Generuje następujące 2 SQL, aby uzyskać dane

SELECT TOP(1) [x].[ForeignExchangeId], [x].[ForeignCurrencyCode], [x].[CurrencyName], [x].[CurrencySymbol], [x].[CountryId], (
SELECT TOP(1) [y].[ExchangeRate] 
FROM [ForeignExchangeRate] AS [y] 
WHERE ((@__Today_0 >= [y].[ValidFrom]) AND ([y].[ValidTo] IS NULL OR ([y]. [ValidTo] >= @__Today_1))) AND ([x].[ForeignExchangeId] = [y].[ForeignExchangeId]) 
)FROM [ForeignExchange] AS [x] 
WHERE [x].[ForeignExchangeId] = @__id_2 

i

SELECT [y0].[ForeignExchangeId], [y0].[ValidFrom], [y0].[ValidTo], [y0].[ExchangeRate] 
FROM [ForeignExchangeRate] AS [y0] 
ORDER BY [y0].[ValidFrom] DESC 

Drugie zapytanie jest taka, która powoduje, że powolność. Jeśli tabela zawiera wiele wierszy, to zasadniczo pobiera całą tabelę i filtruje dane w kodzie

to się zmieniło w najnowszej wersji, jak to używane do pracy w wersji RC EF

jednego innego zapytania I Używane mieć był następujący

  return await _context.CatchPlans 
      .Where(x => x.FishReceiverId == fishReceiverId 
        && x.FisherId == fisherId 
        && x.StockId == stockId 
        && x.SeasonStartDate == seasonStartDate 
        && x.EffectiveDate >= asAtDate 
        && x.BudgetType < BudgetType.NonQuotaed) 
      .OrderBy(x => x.Priority) 
      .ThenBy(x => x.BudgetType) 
      .ToListAsync(); 

i ta kwerenda zakończyła się robi tabela read (całą tabelę który był w dziesiątki tysięcy wierszy), aby uzyskać podzbiór filtra pomiędzy 2 i 10 rekordów. Bardzo nieefektywny. To było jedno zapytanie, które musiałem zastąpić procedurą przechowywaną. Zmniejszono z około 1,5-3,0 sekund do milisekund. I odnotować tę wykorzystywane efektywnie prowadzony przed uaktualnieniem

+0

Czy możesz udostępnić niektóre swoje zapytania EF? – Sampath

+0

zaktualizowany do udostępniania przykładów –

+0

Zamiast przepisywania całkowicie poprawnych zapytań, lepiej uaktualnić do EF Core RTM, gdzie niektóre z tych problemów zostały naprawione (na przykład pierwszy przykład z "Uwzględnij"). Lub, IMHO jeszcze lepiej obniżyć do EF6 i czekać EF Core 1.1 lub nowszej. –

Odpowiedz

6

Jest to znany problem na EF core 1.0 rozwiązania .Powierzchnia teraz jest przekształcenie wszystkich krytycznych zapytań do sync one.The problemu jest na Async zapytaniami prawo now.They'll sort ten numer jest w wersji EF core 1.1.0.Jednak nie został jeszcze wydany.

Oto test zrobione przez rdzeń EF członka zespołu dev:

enter image description here

Możesz dowiedzieć się więcej informacji tutaj: EF Core 1.0 RC2: async queries so much slower than sync

Kolejna propozycja Chciałbym do.That to spróbować twoje pytania z .AsNoTracking(). To również poprawi wydajność zapytania.

.AsNoTracking()

Czasami chcesz uzyskać podmioty z powrotem z kwerendy, ale nie mają te podmioty być śledzone przez kontekst. Może to spowodować lepszą wydajność podczas sprawdzania dużej liczby obiektów w scenariuszach tylko do odczytu .

+0

Jedną z głównych rzeczy, które starałem się powiedzieć o spowolnieniu prędkości zapytań, jest to, że wierzę, że działa szybciej w przedpremierowych wersjach EF niż w najnowszym wydaniu. Oznacza to, że myślę, że coś zostało zepsute między wersją rc2 a wersją 1.0. –

+0

hmm .... Ale na pewno rozwiążą ten problem w wersji 1.1.0 – Sampath

Powiązane problemy