Ich arbeite an einer bestehenden Anwendung. Diese Anwendung liest Daten aus einer großen Datei und speichert sie nach einigen Berechnungen in einer anderen Tabelle.
Aber die Schleife, die das macht (siehe unten), benötigt eine sehr lange Zeit. Da die Datei manchmal 1.000 Datensätze enthält, dauert der gesamte Prozess Tage.
Kann ich diese foreach
Schleife durch etwas anderes ersetzen? Ich habe versucht mit Parallel.ForEach
und es hat geholfen. Ich bin neu in diesem Bereich und schätze Ihre Hilfe.
Nachdem ich die Antworten gelesen hatte, entfernte ich das Async und benutzte den Code wie folgt. Aber das hat die Performance nicht verbessert.
%Vor%Anstatt die sql-Verbindung so oft zu wiederholen, sollten Sie in Betracht ziehen, die gesamte Datenmenge aus dem SQL-Server zu extrahieren und die Daten über den Datensatz zu verarbeiten?
Bearbeiten: Beschlossen, weiter zu erklären, was ich meinte .. Sie können Folgendes tun, Pseudocode wie folgt
Schritt 1: Probieren Sie den Versuch asynchron aus. Es ist nicht richtig implementiert und du blockierst trotzdem. Führen Sie einfach die Prozedur aus und sehen Sie, ob das hilft.
Schritt 2: Verschieben Sie den SqlCommand außerhalb der Schleife und verwenden Sie ihn für jede Iteration erneut. Auf diese Weise entstehen keine Kosten für das Erstellen und Zerstören für jedes Element in der Schleife.
Warnung: Stellen Sie sicher, dass Sie Parameter, die Sie nicht von der vorherigen Iteration benötigen, zurücksetzen / löschen / löschen. Wir haben so etwas mit optionalen Parametern gemacht und hatten von der vorherigen Iteration "bluten-thru", weil wir Parameter, die wir nicht brauchten, nicht bereinigt haben!
Dein größtes Problem ist, dass du das überbrückst:
%Vor%Die gesamte Idee des asynchronen Modells besteht darin, dass der aufrufende Thread (derjenige, der diese Schleife ausführt) alle asynchronen Tasks mit der Begin-Methode startet, bevor er mit den Ergebnissen mit der End-Methode arbeitet. Wenn Sie Thread.Sleep () innerhalb Ihres Hauptaufruf-Threads verwenden, um darauf zu warten, dass ein asynchroner Vorgang abgeschlossen wird (wie Sie hier sind), tun Sie es falsch, und was schließlich geschieht, ist, dass jeder Befehl nacheinander ausgeführt wird , wird aufgerufen und dann gewartet, bevor der nächste startet.
Versuchen Sie stattdessen etwas wie folgt:
%Vor%In SQL am anderen Ende eines Schreibvorgangs ist eine (eine) Festplatte. Sie können selten schneller parallel schreiben. Tatsächlich verlangsamt es parallel dazu oft die Indexfragmentierung. Wenn Sie die Daten vor dem Laden nach primärem (gruppiertem) Schlüssel sortieren können. In einer großen Last sogar andere Schlüssel deaktivieren, laden Daten Rebuild-Schlüssel.
Nicht wirklich sicher, was im asynch passiert, aber sicher hat es nicht getan, was Sie erwartet haben, da es auf sich selbst gewartet hat.
%Vor%Wie wir in den Kommentaren besprochen haben, könnte es effizienter sein, diese Daten im Speicher zu speichern und damit zu arbeiten.
Eine einfache Möglichkeit besteht darin, mit Entity Framework zu beginnen. Entity Framework generiert basierend auf Ihrem Datenbankschema automatisch die Klassen für Sie. Dann können Sie eine gespeicherte Prozedur importieren , die Ihre SELECT-Anweisung enthält. Der Grund, warum ich empfehle, ein gespeichertes Proc in EF zu importieren, ist, dass dieser Ansatz im Allgemeinen effizienter ist als Ihre Abfragen in LINQ gegen EF.
Führen Sie dann den gespeicherten Prozess aus und speichern Sie die Daten in einem List
wie folgt ...
var data = db.MyStoredProc().ToList();
Dann kannst du mit dem data
alles machen, was du willst. Oder wie bereits erwähnt, wenn Sie viele Nachschlagevorgänge für Primärschlüssel durchführen, dann verwenden Sie ToDictionary()
so etwas ...
var data = db.MyStoredProc().ToDictionary(k => k.MyPrimaryKey);
In jedem Fall werden Sie zu diesem Zeitpunkt mit Ihrem data
im Speicher arbeiten.
Es scheint, dass die Ausführung Ihres SQL
-Befehls bestimmte Ressourcen blockiert, und das hat den Grund dafür, dass Sie Async
methods verwenden (meine Vermutung), erzwungen.
Wenn die Datenbank nicht verwendet wird, versuchen Sie einen exklusiven Zugriff darauf. Selbst dann, wenn es aufgrund der Komplexität des Datenmodells einige interne Transaktionen gibt, sollten Sie den Datenbankdesigner konsultieren.