Entity-framework-code ist sehr langsam, wenn mit Include() um ein Vielfaches
Ich habe einige debugging-slow-code, und es scheint, dass der Täter ist die EF code unten geschrieben. Es dauert 4-5 Sekunden, wenn die Abfrage ausgewertet wird zu einem späteren Zeitpunkt. Ich versuche es in unter 1 Sekunde.
Habe ich getestet, mit der SQL Server Profiler, und es scheint, dass eine Reihe von SQL-Skripts ausgeführt werden. Es bestätigt auch, dass es dauert 3-4 Sekunden, bevor Sie SQL server erfolgt mit den Hinrichtungen.
Ich habe gelesen, ähnliche Fragen über die Verwendung von Include() und es scheint, dass es ein performance-Einbußen, wenn es zu benutzen. Ich habe versucht, den split den untenstehenden code in mehrere verschiedene Abfragen, aber es ist nicht so viel Unterschied.
Irgendeine Idee, wie ich die unten schneller ausführen?
Derzeit die web-app, die ich arbeite, ist nur mit einer leeren iframe während der Wartezeit für die unten zu vervollständigen. Wenn ich nicht schneller Ausführung mal habe ich es aufgeteilt und teilweise laden des iframe mit Daten oder mit anderen asynchrone Lösung. Alle Ideen, die hier auch gewürdigt werden!
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
formInstance = context.FormInstanceSet
.Includes(x => x.Include(fi => fi.FormDefinition).Include(fd => fd.FormSectionDefinitions).Include(fs => fs.FormStateDefinitionEditableSections))
.Includes(x => x.Include(fi => fi.FormDefinition).Include(fd => fd.FormStateDefinitions))
.Includes(x => x.Include(fi => fi.FormSectionInstances).Include(fs => fs.FormFieldInstances).Include(ff => ff.FormFieldDefinition).Include(ffd => ffd.FormFieldMetaDataDefinition).Include(ffmdd => ffmdd.ComplexTypePropertyNames))
.Include(x => x.CurrentFormStateInstance)
.Include(x => x.Files)
.FirstOrDefault(x => x.FormInstanceIdentifier == formInstanceIdentifier);
scope.Complete();
}
- Was ist Beinhaltet(mit 's')? Ist es eine proprietäre Erweiterung?
- Ich glaube, es war eine Erweiterung Methode zur Kette gehören unter anderem, wenn das Sinn macht. Ich habe keinen Zugriff auf den code nicht mehr, so kann ich Ihnen nicht genau sagen, was es war, aber das ist meine beste Vermutung, von was ich mich erinnere.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das ist eine Untertreibung! Mehrere
Include
s schnell Blasen bis die SQL-Abfrage Ergebnis sowohl in der Breite und in der Länge. Warum ist das so?tl;dr Mehrere
Include
s Schlag auf den SQL-Ergebnismenge. Bald wird es billiger, Daten zu laden, indem Sie mehrere Datenbank-Aufrufe, anstatt eine mega-Anweisung. Versuchen zu finden die beste Mischung ausInclude
undLoad
Aussagen.Wachstum Faktor
Include
sSagen wir, wir haben
Root
Root.Parent
Root.Children1
undRoot.Children2
Root.Include("Parent").Include("Children1").Include("Children2")
Diese baut eine SQL-Anweisung, die folgende Struktur hat:
Diese
<PseudoColumns>
bestehen aus Ausdrücken wieCAST(NULL AS int) AS [C2],
- und dienen Sie um die gleiche Anzahl von Spalten in allenUNION
-ed-Abfragen. Der erste Teil fügt pseudo-Spalten fürChild2
, der zweite Teil fügt pseudo-Spalten fürChild1
.Dies ist, was es bedeutet, für die Größe der SQL-Ergebnismenge:
SELECT
- Klausel ist die Summe aller Spalten, die in den vier TabellenDa die Gesamtzahl der Datenpunkte ist
columns * rows
, jede weitereInclude
exponentiell steigt die Gesamtzahl der Datenpunkte in der Ergebnismenge. Lassen Sie mich demonstrieren, dass durch die Einnahme vonRoot
wieder, jetzt mit einer zusätzlichenChildren3
Sammlung. Wenn alle Tabellen sind in 5 Spalten und 100 Zeilen, erhalten wir:Einer
Include
(Root
+ 1 Kind Kollektion): 10 Spalten * 100 Zeilen = 1000 Datenpunkten.Zwei
Include
s (Root
+ 2 Kind Sammlungen): 15 Spalten * 200 Zeilen = 3000 data points.Drei
Include
s (Root
+ 3 Kind Sammlungen): 20 Spalten * 300 Reihen = 6000 Datenpunkte.Mit 12
Includes
wären das 78000 Daten Punkte!Umgekehrt, wenn man alle Datensätze für jede Tabelle separat statt 12
Includes
Sie haben13 * 5 * 100
Daten Punkte: 6500, weniger als 10%!Nun diese zahlen sind etwas übertrieben, dass viele dieser Daten werden die Punkte
null
, so dass Sie nicht viel dazu beitragen, um die tatsächliche Größe der Ergebnismenge, die an den client gesendet wird. Aber die Abfrage der Größe und der Aufgabe der query optimizer sicherlich negativ beeinflusst durch die zunehmende Zahl vonInclude
s.Balance
Also mit
Includes
ist eine heikle balance zwischen den Kosten der Datenbank-Aufrufe und Daten-Volumen. Es ist schwer zu geben, eine Faustregel, aber jetzt können Sie sich vorstellen, dass sich das Datenvolumen in der Regel schnell über die Kosten für zusätzliche Anrufe, wenn es mehr als ~3Includes
für Kinder-Kollektionen (aber schon ein bisschen mehr für die ElternIncludes
, dass nur erweitern die Ergebnismenge).Alternative
Die alternative zu
Include
ist zum laden von Daten in separate Abfragen:Dieser lädt alle benötigten Daten in den Kontext des cache. Während dieses Prozesses, EF führt Beziehung Korrektur, durch die es automatisch füllt navigation Eigenschaften (
Root.Children
etc.) von geladenen Entitäten. Das Endergebnis ist identisch zu der Anweisung mitInclude
s, außer einem wichtigen Unterschied: das Kind Sammlungen sind nicht gekennzeichnet als geladen in der entity-state-manager, so dass EF wird versuchen, die trigger lazy loading, wenn Sie auf Sie. Deshalb ist es wichtig, schalten Sie lazy loading.In der Realität, die Sie haben, um herauszufinden, welche Kombination von
Include
undLoad
Aussagen, die am besten für Sie arbeiten.Tun Sie richtig konfiguriert haben, die Beziehungen zwischen allen Entitäten, die Sie versuchen zu 'gehören'? Wenn mindestens eine Person nicht über eine Beziehung zu einigen der anderen Unternehmen, dann ist EF nicht in der Lage zu konstruieren, die eine komplexe Abfrage mit SQL join-syntax - sondern es wird ausgeführt, wie viele Abfragen, wie viele 'schließt' Sie haben. Und natürlich, das führt zu performance-Problemen. Könnten Sie bitte nach den genauen query(-es), das EF generiert, um die Daten zu erhalten?