I dette svar fokuserer jeg på den oprindelige observation:forespørgslen, der genereres af EF, er langsom, men når den samme forespørgsel køres i SSMS, er den hurtig.
En mulig forklaring på denne adfærd er Parametersniffing .
Så EF genererer en forespørgsel, der har få parametre. Første gang du kører denne forespørgsel, opretter serveren en eksekveringsplan for denne forespørgsel ved hjælp af værdier af parametre, der var gældende i den første kørsel. Den plan er normalt ret god. Men senere kører du den samme EF-forespørgsel ved at bruge andre værdier for parametre. Det er muligt, at for nye værdier af parametre er den tidligere genererede plan ikke optimal, og forespørgslen bliver langsom. Serveren bliver ved med at bruge den tidligere plan, fordi det stadig er den samme forespørgsel, bare værdierne af parametre er forskellige.
Hvis du på dette tidspunkt tager forespørgselsteksten og prøver at køre den direkte i SSMS, vil serveren oprette en ny eksekveringsplan, fordi det teknisk set ikke er den samme forespørgsel, der er udstedt af EF-applikationen. Selv én tegnforskel er nok, enhver ændring i sessionsindstillingerne er også nok til, at serveren kan behandle forespørgslen som en ny. Som et resultat har serveren to planer for den tilsyneladende samme forespørgsel i sin cache. Den første "langsomme" plan er langsom for de nye værdier af parametre, fordi den oprindeligt blev bygget til forskellige parameterværdier. Den anden "hurtige" plan er bygget til de aktuelle parameterværdier, så den er hurtig.
Artiklen Langsom i applikationen, hurtig i SSMS af Erland Sommarskog forklarer dette og andre relaterede områder meget mere detaljeret.
Der er flere måder at kassere cachelagrede planer og tvinge serveren til at genskabe dem. Ændring af tabellen eller ændring af tabelindekserne burde gøre det - det bør kassere alle planer, der er relateret til denne tabel, både "langsom" og "hurtig". Så kører du forespørgslen i EF-applikation med nye værdier af parametre og får en ny "hurtig" plan. Du kører forespørgslen i SSMS og får en anden "hurtig" plan med nye værdier af parametre. Serveren genererer stadig to planer, men begge planer er hurtige nu.
En anden variant er at tilføje OPTION(RECOMPILE)
til forespørgslen. Med denne mulighed vil serveren ikke gemme den genererede plan i sin cache. Så hver gang forespørgslen kører, vil serveren bruge faktiske parameterværdier til at generere den plan, som (den mener) ville være optimal for de givne parameterværdier. Ulempen er en ekstra overhead af plangenereringen.
Husk at serveren stadig kunne vælge en "dårlig" plan med denne mulighed på grund af forældede statistikker, for eksempel. Men i det mindste ville parametersniffing ikke være et problem.
Dem, der spekulerer på, hvordan man tilføjer OPTION (RECOMPILE)
tip til forespørgslen, der er genereret af EF, se på dette svar:
https://stackoverflow.com/a/26762756/4116017