Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Wydajność zapytań Entity Framework różni się ekstremalnie od wykonywania surowego kodu SQL

W tej odpowiedzi skupiam się na oryginalnej obserwacji:zapytanie generowane przez EF jest powolne, ale gdy to samo zapytanie jest uruchamiane w SSMS, jest szybkie.

Jednym z możliwych wyjaśnień tego zachowania jest Podsłuchiwanie parametrów .

Tak więc EF generuje zapytanie, które ma kilka parametrów. Przy pierwszym uruchomieniu tego zapytania serwer tworzy plan wykonania dla tego zapytania przy użyciu wartości parametrów, które obowiązywały w pierwszym uruchomieniu. Ten plan jest zazwyczaj całkiem niezły. Ale później możesz uruchomić to samo zapytanie EF przy użyciu innych wartości parametrów. Możliwe, że dla nowych wartości parametrów wygenerowany wcześniej plan nie jest optymalny i zapytanie staje się wolniejsze. Serwer nadal używa poprzedniego planu, ponieważ nadal jest to to samo zapytanie, tylko wartości parametrów są różne.

Jeśli w tym momencie weźmiesz tekst zapytania i spróbujesz go uruchomić bezpośrednio w SSMS, serwer utworzy nowy plan wykonania, ponieważ technicznie nie jest to to samo zapytanie, które jest wystawiane przez aplikację EF. Wystarczy różnica jednego znaku, każda zmiana w ustawieniach sesji wystarczy, aby serwer potraktował zapytanie jako nowe. W rezultacie serwer ma w swojej pamięci podręcznej dwa plany dla pozornie tego samego zapytania. Pierwszy „wolny” plan jest powolny dla nowych wartości parametrów, ponieważ został pierwotnie zbudowany dla różnych wartości parametrów. Drugi „szybki” plan jest zbudowany dla bieżących wartości parametrów, więc jest szybki.

Artykuł Wolno w aplikacji, szybko w SSMS autorstwa Erlanda Sommarskoga wyjaśnia ten i inne powiązane obszary bardziej szczegółowo.

Istnieje kilka sposobów na odrzucenie planów z pamięci podręcznej i zmuszenie serwera do ich regeneracji. Zmiana tabeli lub zmiana indeksów tabeli powinna wystarczyć - powinna odrzucić wszystkie plany, które są związane z tą tabelą, zarówno „wolne”, jak i „szybkie”. Następnie uruchamiasz zapytanie w aplikacji EF z nowymi wartościami parametrów i otrzymujesz nowy „szybki” plan. Uruchamiasz zapytanie w programie SSMS i otrzymujesz drugi „szybki” plan z nowymi wartościami parametrów. Serwer nadal generuje dwa plany, ale oba plany są teraz szybkie.

Innym wariantem jest dodanie OPTION(RECOMPILE) do zapytania. Dzięki tej opcji serwer nie będzie przechowywać wygenerowanego planu w swojej pamięci podręcznej. Tak więc za każdym razem, gdy zapytanie zostanie uruchomione, serwer użyje rzeczywistych wartości parametrów do wygenerowania planu, który (uważa) będzie optymalny dla danych wartości parametrów. Minusem jest dodatkowy koszt generowania planu.

Pamiętaj, że serwer nadal może wybrać „zły” plan z tą opcją, na przykład ze względu na nieaktualne statystyki. Ale przynajmniej wąchanie parametrów nie stanowiłoby problemu.

Ci, którzy zastanawiają się, jak dodać OPTION (RECOMPILE) wskazówka do zapytania generowanego przez EF spójrz na tę odpowiedź:

https://stackoverflow.com/a/26762756/4116017



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SMALLDATETIMEFROMPARTS() Przykłady w SQL Server (T-SQL)

  2. Czy w Microsoft SQL Server istnieje typ danych logicznych, taki jak w MySQL?

  3. Odwołanie do kursora programu SQL Server (składnia itp.)

  4. Nie można powiązać wieloczęściowego identyfikatora TextBox1.Text w C# ASP.NET?

  5. Nieudane wywołanie ODBC z procedurą składowaną — zapytanie przekazujące