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
Czy możesz udostępnić niektóre swoje zapytania EF? – Sampath
zaktualizowany do udostępniania przykładów –
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. –