2013-03-23 7 views
18

Ich habe kürzlich mein Entity-Modell von einem ObjectContext mit 4.1 zu einem DbContext mit 5.0 verschoben. Ich beginne zu bereuen dies zu tun, weil ich eine sehr schlechte Leistung bei der Abfrage mit dem DbContext vs ObjectContext bemerke. Hier ist das Testszenario:DbContext Abfrage Leistung schlecht vs ObjectContext

Beide Kontexte verwenden die gleiche Datenbank mit etwa 600 Tabellen. LazyLoading und ProxyCreation sind für beide deaktiviert (nicht im Codebeispiel gezeigt). Beide haben vorgenerierte Ansichten.

Der Test führt zunächst einen Aufruf zum Laden des Metadatenarbeitsbereichs durch. Dann führe ich in einer for-Schleife, die 100 Mal ausgeführt wird, einen Kontext neu aus und führe einen Aufruf aus, der die ersten 10 aufruft. (Ich erstelle den Kontext in der for-Schleife, da dies in einem WCF-Dienst verwendet wird jedes Mal) der Kontext

for (int i = 0; i < 100; i++) 
{ 
    using (MyEntities db = new MyEntities()) 
    { 
     var a = db.MyObject.Take(10).ToList(); 
    } 
} 

Als ich betreibe diese mit dem Object es etwa 4,5 Sekunden dauert. Wenn ich es mit dem DbContext starte, dauert es etwa 17 Sekunden. Ich profilierte dies mit RedGate Performance-Profiler. Für den DbContext scheint der Hauptschuldiger eine Methode namens UpdateEntitySetMappings zu sein. Dies wird bei jeder Abfrage aufgerufen und scheint den Metadatenarbeitsbereich abzurufen und alle Elemente im OSpace durchlaufen zu lassen. AsNoTracking hat nicht geholfen.

EDIT: Um ein besseres Detail zu geben, hat das Problem mit der Erstellung \ Initialisierung eines DbSet vs ein ObjectSet, nicht die eigentliche Abfrage zu tun. Wenn ich mit dem ObjectContext einen Aufruf mache, dauert es im Durchschnitt 42ms, um das ObjectSet zu erstellen. Wenn ich mit dem DbContext aufrufe, dauert es etwa 140ms, um das interne dbset zu erstellen. Sowohl ObjectSet als auch DbSet führen einige Entitätsgruppen-Mapping-Suchen aus dem Metadatenarbeitsbereich aus. Was ich bemerkt habe, ist, dass das DbSet dies für ALLE Typen im Arbeitsbereich tut, während das ObjectSet dies nicht tut. Ich vermute (habe es nicht ausprobiert), dass ein Modell mit weniger Tabellen weniger Leistungsdifferenz hat.

Antwort

2

DbContext ist ein Wrapper für ObjectContext. Hier ist gut answer über Ihre Frage. Es ist möglich, dass, um die Verwendung zu erleichtern, die Leistung geopfert wird.

-3

Ich benutze Simple.Data, um Millionen von Datensätzen abzufragen, und es funktioniert ziemlich gut und schnell.

4

Ich habe auch durch die Underperformance des Codes erster Ansatz besorgt, und ich habe einige Benchmarks in einem Szenario ähnlich wie bei Ihnen durchgeführt

http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html

Die Ergebnisse waren keine Überraschung, da die DbContext ist ein Wrapper über ObjectContext, muss die Leistung zugunsten der Einfachheit geopfert werden. Allerdings zeigen meine Tests, dass:

  • desto mehr Datensätze abrufen Sie desto geringer ist die Differenz
  • die mehr Datensätze abrufen Sie desto wichtiger ist es Tracking auszuschalten ist, wenn Sie schneller sein wollen

zum Beispiel nur 10 Datensätze abrufen

enter image description here

Hinweis zunächst, dass Code ist deutlich langsamer als modellieren und es gibt keinen merklichen Unterschied zwischen Tracking und Tracking - beide Beobachtungen sind genau wie bei Ihnen.

Wenn jedoch 10000 Zeilen abrufen Sie haben

enter image description here

Beachten Sie, dass es fast keinen Unterschied zwischen Code ist in erster Modell zuerst in der notracking Version. Beide funktionieren auch überraschend gut, fast so schnell wie der rohe ado.net Datenreader.

Bitte folgen Sie meinem Blog-Eintrag für weitere Details.

Dieser einfache Benchmark half mir, die Natur des Codes zuerst zu akzeptieren. Ich bevorzuge es immer noch für kleinere Projekte wegen zweier Features: POO-Entitäten und Migrationen. Auf der anderen Seite würde ich niemals eines der beiden für ein Projekt auswählen, bei dem Leistung eine kritische Anforderung ist. Dies bedeutet effektiv, dass ich wahrscheinlich nie wieder den Ansatz des ersten Modells verwenden werde.

(Nebenbemerkung: meine Benchmark zeigt auch, dass es etwas falsch mit nHibernate ist Ich habe noch niemanden gefunden, mir zu helfen diese auch zu erklären, obwohl ich zwei unabhängige Entwickler, die NH nutzen täglich konsultiert haben.)

Verwandte Themen