Entity Framework 4 -: Schlechte performance mit SQL Server 2008
Ich bin die Entwicklung einer software basierend auf Entity Framework zum verarbeiten von Daten in einer MS SQL Server 2008-Datenbank.
[Trouble 1]
Ich habe gerade versucht, fügen Sie einige kleine Daten (über 2 Mb) von meinem Programm auf die Datenbank : die sehr schlechte Leistung ! Es dauert mehr als 1 minute einfügen dieser Daten !
Ich habe versucht, zu generieren vorkompilierte sichten, ich habe das gleiche Ergebnis 🙁
Allen meinen code verwenden Sie ein business-Schicht automatisch generiert aus .edmx-Datei mit T4-template) zur Verwaltung von Daten in einer service-Schicht. Es ist sehr praktisch zum navigieren in den Beziehungen von Objekten.
Wie verbessere ich die performance von diesen Einsätzen mit Entity Framework ?
[Trouble 2]
Auch, vor dem einfügen der Daten in Datenbank mit SaveChanges () - Methode, fülle ich mein Objekt Kontext mit AddObject () - Methode. Ich füge über 100 000 kleine Objekte (etwa 2 Mb), um meine Objekt-Kontext mit AddObject() : es dauert eine sehr lange Zeit (mehr als 10 Minuten) !
Wie kann ich abnehmen in dieser Zeit ?
UPDATE
Mein Programm speichern, müssen Sie mehr als 50 Mb in der Datenbank in weniger als 2-3 Minuten ? Denkst du es wird möglich sein, mit EF ?
- Entity Framework ist ein Kompromiss zwischen den anfänglichen Benutzerfreundlichkeit und Leistung. Wenn Sie interessiert sind, in der Leistung, Weg von Entity Framework
- das ist Wild, wenig hilfreich. Dies ist nicht die normale Leistung. Entfernen des EF könnte nicht zu beheben, und in jedem Fall würde, wie das Kurieren der Akne mit Enthauptung. Patrice muss Profil die app um das problem zu finden, gehen Sie nicht die Schuld-tools nach dem Zufallsprinzip.
- Stuntz: Also, Ihrer Meinung nach, was jemand Profil EF ist hilfreicher? Heheh
- Es ist absolut nützlich für Patrice Profil der app in der Entwicklung, als zu umschreiben Infrastruktur nach dem Zufallsprinzip. Architektur von Vorurteilen, ist nur selten eine erfolgreiche Strategie.
- Stuntz: ich war der Annahme, dass es eine neue app, die funktioniert noch nicht, und hat unüberwindliche performance-Probleme. Genau das, was Sie erwarten würden, von einem EF-app
- das ist nicht das, was ich erwarten würde, aus einem EF-app. Aber dann wieder, ich bin nicht die Art von person, die die Schuld-tools für meine Probleme.
- Was bedeutet "2 Mo" bedeuten?
- 2 Mb : 20 Byte Objekt (20 bytes x 100 000 Objekte = 2 000 000 Mb )
- Sie sind also das einfügen von rund 100 Objekten aus die möglicherweise eine Int-und vielleicht eine sehr kurze Zeichenfolge mit 16 Zeichen oder weniger?
- 1 int + 1 dezimal
- Was ist die Quelle dieser int + dezimal? Warum ist es, dass Sie sich einfügen müssen 100000 von diesen Paaren? Sind Sie vor dem Befüllen eine lookup-Tabelle? Erfassen von sensor-Daten? Bitte erzählen Sie uns mehr über Ihr problem.
- Es ist wissenschaftlicher Ergebnisse. Ich brauche, um es zu speichern, die für weitere Statistiken. In der Tat, ich brauche, um zu sparen Sie mehr als 50 Mb in 2-3 Minuten.
- Sind Sie auf einfügen jedes Element in der Datenbank getrennt, oder sind Sie mit dem hinzufügen, daß Sie alle Ihre Daten-Objekte und dann das insert in eine SQL-Anweisung? Wenn Sie dabei die erste, das könnte die Ursache Ihrer Leistung. Sie wiederholt die Datenbank wird die Leistung erheblich beeinträchtigen. Ich schlage vor, Sie Profil als @Craig sagte.
- Ich bin das hinzufügen Sie alle auf meiner Daten-Objekte und dann tun Sie den Einsatz mit SaveChanges()
Du musst angemeldet sein, um einen Kommentar abzugeben.
Könnten Sie die Entity Framework Profiler zu überprüfen, was SQL generiert wird. Dieses Werkzeug verfügt über eine 30-tägige Kostenlose Testversion. Es behauptet auch, dass Sie es tun können, "die Analyse und Erkennung der häufigsten Fallstricke bei der Verwendung von Entity Framework".
Gibt es auch diese Artikel auf EF-tuning
Bearbeiten
Basierend auf Ihren änderungen EF ist nicht der Weg zu gehen. Sie tun müssen, um eine bulk insert, um die Daten schnell an. Haben Sie einen Blick auf diese link, wo ich jemandem geholfen reduzieren die Ladezeit von 10 Stunden auf 6 Minuten.
Gibt es hier mehrere Möglichkeiten.
Der Datenbank hardware möglicherweise nicht bis zu der Aufgabe Handhabung von 100.000 Einsätze. Wie viele Tabellen sind beteiligt? Gibt es Nebenleistungen überlegungen wie der Trigger gefeuert? Ist die Datenbank Speicher eingeschränkt?
Den Web-server hardware möglicherweise nicht bis zu der Aufgabe, die Verarbeitung, die viel laden. Wo ist die Datenflut? Wie lange dauert es zur übertragung an den web-server? Wie viele Einsätze/sec ist der web-server tatsächlich das senden an die Datenbank-server?
Summe bis, Sie haben zu Profil, um genau herauszufinden, wo die Engpässe sind. Mit den Informationen, die Sie gegeben haben, so weit es konnte überall sein.
Müssen Sie führen einen profiler auf dem web-server, und Sie müssen, verwenden Sie SQL Profiler auf dem Datenbank-server. Darüber hinaus sollten Sie die Kontrolle beider Maschinen auf CPU -, Speicher-und Netzwerk-Auslastung-Diagramme beim laden der Daten.
Sobald Sie haben alle der Daten Sie sollten in der Lage sein, um herauszufinden, wo das problem ist.
UPDATE
Als seitliche Anmerkung, die EF zu erstellen hat mindestens 100.000 Objekte, um die Daten, die Sie hochladen (einer für jeden Datensatz). Dieser hat seinen eigenen overhead, das ist der Grund, warum ORM ' s sind in der Regel nicht eine gute Idee für große einfügen/aktualisieren von Daten.
UPDATE 2
Wenn Sie mit dem client und der Datenbank-server auf exakt dieselbe desktop-Rechner, dann Sie haben wahrscheinlich hardware-Probleme. Hoffentlich haben Sie eine multi-core-system mit mindestens 4 GB ram. Alles, was auf deinem system Los ist, um im Wettbewerb um Ressourcen: visual studio, SQL-Server, die app selbst, und was Sie sonst passieren, um ausgeführt werden. Studio und SQL Server sind, Arbeitsspeicher und CPU-hogs. (FYI - SQL-server melden nicht alles, um den task-manager)
Punkt ist, es sei denn, Sie sind die Bereitstellung der app mit einer eingebetteten sql-server diese nicht zu nahe zu kommen, zu einem realen Welt zu testen und die Leistung, die Sie zu sehen sind, oder deren fehlen hat keine Beziehung zu einem realen Szenario.
EF (und LINQ2SQL für diese Angelegenheit) nicht ein einziges update/insert pro Datensatz. Dies führt in der Regel in weniger dann eine akzeptable Leistung für bulk-inserts/updates.
Die Arbeit ist das erstellen von gespeicherten Prozeduren ist, der diese Aufgaben für Sie. Dies ist eine akzeptable Lösung in den meisten Fällen, wenn Sie diese Vorgänge auf eine kleine Anzahl von Objekt-Typen, in dem Fall ist es noch möglich zu verwenden, EF, und schreiben die SPs manuell, und fügen Sie dann zu der EDMX.
Sie können google für die Verwendung von gespeicherten Prozeduren in EF.
Chancen sind, dass es nicht Entity Framework, sondern Ihre Datenbank-schema, dass der Schuldige ist, z.B. durch schlecht gruppierten Indizes oder zu viele Indizes.
Sehen Sie die generierte SQL von Entity Framework mit dem ObjectQuery.ToTraceString Eigenschaft.
Falls die generierte SQL von Entity Framework ist nicht ausreichend für Ihre Bedürfnisse Sie sind in der Lage, nutzen Sie Ihre eigenen gespeicherten Prozeduren zum erstellen, aktualisieren und löschen von Operationen.
Können Sie ein Profil der Abfragen mit Hilfe von SQL Server Profiler und verwenden Sie dann den Database Engine Tuning Advisor, um zu bestimmen, bessere Statistiken und Indizes hinzufügen.
AFTER INSERT
trigger, einen index hinzufügen könnte in der Tat machen die legen schneller. "Profil und finde, das problem" ist die einzig richtige Antwort hier. Es gibt nicht genügend Informationen in Patrice ' s Frage noch etwas zu sagen.In der ursprünglichen Frage, bekomme ich den Eindruck, dass rund 100.000 Objekte werden alle auf einmal erstellt und zu einem einzigen Aufruf von SaveChanges gemacht wird. Diese Art von großen Einheit der Arbeit, wo gibt es einen einzigen Aufruf von SaveChanges ist fast immer eine sehr schlechte Leistung Idee für das Entity Framework. Ich würde versuchen, die Aufteilung die Dinge in eine Reihe von Chargen mit vielleicht 100 Objekte oder so und SaveChanges aufrufen zwischen jeder charge. In der Tat würde ich auch entsorgen, die den Kontext und erstellen Sie eine neue, zwischen den Chargen, weil sonst Sie am Ende mit diesen Objekten in der Status-manager auf einmal die erlegt overhead. Sie würden wahrscheinlich benötigen, um zu Experimentieren mit verschiedenen Losgrößen, finden Sie die besten Anzahl.
Auch, möchten Sie vielleicht zu prüfen, welche Art von Entitäten, die Sie verwenden. Wenn Sie poco-Entitäten es ist ein gewisser Aufwand die Erkennung von änderungen ist nicht vorhanden, wenn Sie die Verwendung von Klassen, die für die Einführung IEntityWithChangeTracking (oder Erben von EntityObject, die die diese Schnittstelle implementiert).
Als andere haben schon darauf hingewiesen, mehr oder weniger, Entity Framework arbeitet, indem er eine Anweisung für jedes Objekt, und dann eine zusätzliche Anweisung zu Holen, zurück zugewiesene ID-Wert von der Datenbank.
Dies ist enorm langsam beim laufen auf viele Objekte, vor allem, wenn die round-trip-Zeit, um die Datenbank-server ist etwas über 1 Millisekunde.
Um die Leistung zu verbessern, wenn die Speicherung von vielen Objekten in die Datenbank, verwenden Sie SqlBulkCopy-Klasse anstelle von Entity Framework.
Finden Sie die vollständige Vergleich zwischen Entity Framework und SqlBulkCopy in diesem Artikel: Wie Bulk Insert-Komplexe Objekte in SQL Server-Datenbank
Erlebe ich ein ähnliches Problem mit meinem aktuellen Projekt. Ich befestigt Sie SQL Profiler und der Startschuss für meinen Prozess. Es scheint, dass das Entity Framework startet eine SQL-Transaktion für jeden INSERT-oder UPDATE-jedes mal, wenn änderungen gespeichert werden.
Ich bin mir nicht sicher, ob das hat etwas zu tun mit der Frage, aber ich würde führen Sie SQL Profiler, und die Ergebnisse untersuchen. Ich würde auch überwachen Sie Ihre Festplattennutzung (liest und schreibt) auf dem SQL-Feld (wenn möglich) und sehen, ob es irgendwelche roten Fahnen.