sql >> Databáze >  >> RDS >> Sqlserver

Výkon dotazů Entity Framework se extrémně liší s nezpracovaným prováděním SQL

V této odpovědi se zaměřuji na původní pozorování:dotaz generovaný EF je pomalý, ale když je stejný dotaz spuštěn v SSMS, je rychlý.

Jedním z možných vysvětlení tohoto chování je Sniffování parametrů .

EF tedy generuje dotaz, který má málo parametrů. Při prvním spuštění tohoto dotazu server vytvoří plán provádění pro tento dotaz pomocí hodnot parametrů, které byly platné při prvním spuštění. Ten plán je většinou dobrý. Později však spustíte stejný dotaz EF s jinými hodnotami parametrů. Je možné, že pro nové hodnoty parametrů není dříve vygenerovaný plán optimální a dotaz se zpomalí. Server nadále používá předchozí plán, protože je to stále stejný dotaz, jen hodnoty parametrů jsou jiné.

Pokud v tuto chvíli vezmete text dotazu a pokusíte se jej spustit přímo v SSMS, server vytvoří nový plán provádění, protože technicky se nejedná o stejný dotaz, který zadává aplikace EF. Stačí i jeden znakový rozdíl, jakákoliv změna v nastavení relace také stačí k tomu, aby server považoval dotaz za nový. Výsledkem je, že server má ve své mezipaměti dva plány pro zdánlivě stejný dotaz. První „pomalý“ plán je pomalý pro nové hodnoty parametrů, protože byl původně sestaven pro různé hodnoty parametrů. Druhý „rychlý“ plán je vytvořen pro aktuální hodnoty parametrů, takže je rychlý.

Článek Pomalá aplikace, rychlá SSMS od Erlanda Sommarskoga vysvětluje tuto a další související oblasti mnohem podrobněji.

Existuje několik způsobů, jak zrušit plány uložené v mezipaměti a donutit server, aby je znovu vytvořil. Změna tabulky nebo změna indexů tabulky by to měla udělat - měla by zahodit všechny plány, které s touto tabulkou souvisejí, „pomalé“ i „rychlé“. Poté spustíte dotaz v EF aplikaci s novými hodnotami parametrů a získáte nový "rychlý" plán. Spustíte dotaz v SSMS a získáte druhý „rychlý“ plán s novými hodnotami parametrů. Server stále generuje dva plány, ale oba jsou nyní rychlé.

Další variantou je přidání OPTION(RECOMPILE) na dotaz. S touto volbou server neuloží vygenerovaný plán do své mezipaměti. Takže pokaždé, když se dotaz spustí, server použije skutečné hodnoty parametrů ke generování plánu, který (myslí si), že by byl optimální pro dané hodnoty parametrů. Nevýhodou je přidaná režie generování plánu.

Uvědomte si, že server by s touto možností stále mohl zvolit "špatný" plán například kvůli zastaralým statistikám. Ale alespoň sniffování parametrů by nebyl problém.

Ti, kteří se zajímají o to, jak přidat OPTION (RECOMPILE) nápověda k dotazu, který generuje EF, podívejte se na tuto odpověď:

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



  1. SQL odlišné více sloupců

  2. Python převádí výsledek dotazu mysql na json

  3. Vložení databáze php nefunguje podle plánu

  4. Rozdělení kontrolní tabulky serveru SQL Server