sql >> Databasteknik >  >> RDS >> Sqlserver

Entity Framework-frågeprestanda skiljer sig extremt med rå SQL-exekvering

I det här svaret fokuserar jag på den ursprungliga observationen:frågan som genereras av EF är långsam, men när samma fråga körs i SSMS är den snabb.

En möjlig förklaring till detta beteende är parametersniffning .

Så EF genererar en fråga som har få parametrar. Första gången du kör den här frågan skapar servern en exekveringsplan för den här frågan med hjälp av värden för parametrar som gällde under den första körningen. Den planen brukar vara ganska bra. Men senare kör du samma EF-fråga med andra värden för parametrar. Det är möjligt att för nya parametrars värden är den tidigare genererade planen inte optimal och frågan blir långsam. Servern fortsätter att använda den tidigare planen, eftersom det fortfarande är samma fråga, bara parametrarnas värden är olika.

Om du i detta ögonblick tar frågetexten och försöker köra den direkt i SSMS kommer servern att skapa en ny exekveringsplan, eftersom det tekniskt sett inte är samma fråga som utfärdas av EF-applikationen. Även en teckenskillnad räcker, alla ändringar i sessionsinställningarna räcker också för att servern ska behandla frågan som en ny. Som ett resultat har servern två planer för till synes samma fråga i sin cache. Den första "långsamma" planen är långsam för de nya parametrarnas värden, eftersom den ursprungligen byggdes för olika parametervärden. Den andra "snabba" planen är byggd för de aktuella parametervärdena, så den är snabb.

Artikeln Långsam i applikationen, snabb i SSMS av Erland Sommarskog förklarar detta och andra relaterade områden mycket mer detaljerat.

Det finns flera sätt att kassera cachade planer och tvinga servern att återskapa dem. Att ändra tabellen eller ändra tabellindexen borde göra det - det bör förkasta alla planer som är relaterade till denna tabell, både "långsamt" och "snabbt". Sedan kör du frågan i EF-applikationen med nya värden på parametrar och får en ny "snabb" plan. Du kör frågan i SSMS och får en andra "snabb" plan med nya parametrar. Servern genererar fortfarande två planer, men båda planerna är snabba nu.

En annan variant är att lägga till OPTION(RECOMPILE) till frågan. Med detta alternativ skulle servern inte lagra den genererade planen i sin cache. Så varje gång frågan körs skulle servern använda faktiska parametervärden för att generera planen som (den tror) skulle vara optimal för de givna parametervärdena. Nackdelen är en extra overhead av plangenereringen.

Tänk på att servern fortfarande kan välja en "dålig" plan med detta alternativ på grund av föråldrad statistik, till exempel. Men, åtminstone, parametersniffning skulle inte vara ett problem.

De som undrar hur man lägger till OPTION (RECOMPILE) ledtråd till frågan som genereras av EF ta en titt på det här svaret:

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



  1. Beräkna skillnaden mellan två datumtider

  2. Hur man zippar en .csv-fil och bifogar i e-post Oracle plsql utan att använda Java

  3. Var kan jag hitta listan över SQLException-felkoder för MySQL?

  4. error (objektet 'datetime.datetime' har inget attribut 'split') i django 1.11.4