EF-6-Parameter-Sniffing
Habe ich eine dynamische Abfrage, die ist einfach zu gross hier zu setzen. Sicher zu sagen, dass in seiner aktuellen form ist es nutzt eine CLR-Prozedur, um dynamisch zu erstellen-Verknüpfungen basierend auf der Anzahl der Suchparameter übergeben, dann nimmt das Ergebnis und schließt es zu den detaillierten Tabellen zurück zu bringen Attribute, die wichtig für den end-user. Ich habe Umgerechnet die ganze Abfrage in LINQ to Entities und dem, was ich gefunden habe, ist, dass der SQL-Code, den es produziert, ist effizient genug, um den job zu erledigen, jedoch laufen über EF 6, die Abfrage timesout. Wobei die resultierende SQL-und es läuft in SSMS läuft in 3 oder weniger Sekunden. Ich kann mir nur vorstellen, dass mein problem ist die parameter-sniffing. Ich habe versucht, aktualisieren der Statistiken für jede Tabelle in der Datenbank und dieser hat das problem nicht gelöst.
Meine Frage ist:
Kann ich irgendwie einbetten-Optionen wie eine "OPTION RECOMPILE" über EF?
- würde gerne vergleichen, Notizen mit, die Sie auf diese Arten von dynamischen sql-Projekte.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ist es möglich, das abfangen feature von EF6 zu manipulieren, um seine internen SQL-Befehle vor der Ausführung in DB, zum Beispiel das hinzufügen
option(recompile)
am Ende des Befehls:Um es zu verwenden, fügen Sie die folgende Zeile am Anfang der Anwendung:
!(command is SqlCommand)
etwas verhindert?OPTION(OPTIMIZE FOR UNKNOWN)
stattdessen zu deaktivieren, die parameter sniffing, aber unabhängig, Sie wird mit der Tatsache auseinandersetzen, dies ist ein global change und der DBA wird denken, Sie sind hoch auf crack.Ich mag VahidN's-Lösung, tun-up wählen ihn, aber ich möchte mehr Kontrolle über wenn es passiert. Es stellt sich heraus, dass die DB Abfangjäger sind sehr global, und ich wollte nur das geschehen auf spezifische Kontexte in bestimmten Szenarien.
Hier setzen wir die Basis, um auch Unterstützung für das hinzufügen von query hints, konnte ein-und ausgeschaltet werden, wie gewünscht.
Da ich oft stellen die Methode für die übergabe einer Verbindungszeichenfolge, die ich ebenfalls im Lieferumfang enthalten Unterstützung für das.
Unten geben würde, Ihren Kontext ein flag zum aktivieren/deaktivieren Sie die Hinweis-programmatisch, durch die Verlängerung der partiellen Klasse EF erzeugt. Wir warfen auch das kleine Stück wiederverwendet code in der Interceptor in seine eigene Methode.
Kleine Schnittstelle
DB-Befehl, Abfangjäger
Erweitern von Entity-Kontext Hinzufügen IQueryHintable
Register DB-Command-Interceptor (global.asax)
Aktivieren Kontext weit
Ein-oder Ausschalten
Rief ich diese HintWithRecompile, weil Sie vielleicht auch umsetzen wollen, eine HintOptimizeForUnknown , oder andere Abfrage Hinweise.
OPTION(OPTIMIZE FOR UNKNOWN)
WITH recompile
oderFREEPROCCACHE
. Weitere, wenn Sie die Kommentare Lesen von den SELBEN Autoren, die Sie zitieren den marketing-slogan "Optimiert Für Mittelmäßig", stellt Sie fest: Für diese beiden Gründe (und ich bin wirklich leidenschaftlich über #2), ich bin viel mehr zugunsten von einer OPTIMIZE FOR-Hinweis auf einige Verfahren, wenn [ ... ] - parameter sniffing [...]"Gleiche für mich wie für @Greg, ermöglicht dieses system breit war keine option, also schrieb ich dieses kleine utility-Klasse, die können temporäre hinzufügen-option(recompile) zu ausgeführten Abfragen innerhalb einer OptionRecompileScope.
Beispiel für die Verwendung
Umsetzung
Ich hatte ein ähnliches problem. Am Ende habe ich entfernt, den zwischengespeicherten Abfrageplan mit diesem Befehl:
In Ordnung, um Ihren plan in Griff, können Sie die folgende Abfrage verwenden:
austauschen der Inhalt der "gefällt mir" - Klauseln mit entsprechenden Stücke Ihrer Abfrage.
Können Sie sehen, meine ganze Frage auf:
SQL-Abfragen Mit Entity Framework Läuft Langsamer, verwendet schlechte Abfrage-plan
Hatte einen ähnlichen Fall in EF Core 2, aber es unterscheidet sich nur in der Interceptor-Implementierung.
Da dieser thread hat mir geholfen, die meisten, möchte ich meine Umsetzung mit Euch, auch wenn die OP gefragt, für EF 6.
Außerdem verbesserte ich @Oskar Sjöberg und @Greg Lösung ein bisschen, um herauszufinden, das Abfragen, die verlängert werden sollte, mit der option recompile.
EF-Core-2-der Interceptor ist ein wenig knifflig und ein bisschen anders.
Kann realisiert werden über Paket
Microsoft.Extensions.DiagnosticAdapter
und den folgenden codeDen Interceptor selbst dann muss Ihre Methoden sind gekennzeichnet mit dem entsprechenden
DiagnosticName
Annotation.Den tweak ich gab die Interceptor wurde, dass es sucht nach bestimmten tags (sql-Kommentare) in die Befehl um Abfragen, die sollten erweitert werden mit die gewünschte option.
Markieren Sie eine Abfrage verwenden Sie den recompile-option, Sie einfach hinzufügen ein
.TagWith(Constants.SQL_TAG_QUERYHINT_RECOMPILE)
auf die Abfrage, ohne Sie zu belästigen, um mit der Einstellung einen bool auf true und wieder auf false.Diese Weise müssen Sie sich nicht auch ein problem mit parallelen Abfragen abgefangen werden und alle verlängert, mit einer option recompile wegen einem einzigen bool HintWithRecompile.
Die Konstante tag-strings sind so konzipiert, dass Sie nur in einem sql Kommentar und nicht Teil der Abfrage selbst.
Ich konnte keine Lösung finden, zu analysieren, nur der tag-Teil (detail von EF), so dass der gesamte sql-Befehl wird analysiert und Sie nicht möchten, fügen Sie eine neu kompilieren, da einige text in der Abfrage entspricht Ihre Flagge.
Dem "Optimize for Unknown" Teil, die verbessert werden können mit dem Befehl parameter-Eigenschaft, aber ich werde verlassen, dass bis zu Ihnen.