Hallo Leute,
ich habe folgendes Problem. Ich lese aus einem Verzeichnis ca. 15000 XML-Dateien aus und schreibe deren Inhalt in eine Datenbank. Da es ein sehr zeitaufwendiger Vorgang ist, setzte ich den BackGroundWorker ein. Das funktioniert soweit ganz gut, außer das nach ca. 2000 Dateien der Importprozess immer langsamer wird. Woran kann das liegen?
Mfg
mcpd
Hallo mcpd,
Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5, aber ich tippe auf den GC. Um genaueres zu sagen, verwende einen Profile.
Gib nicht mehr benötigte Objekte frei.
Wie importierst du in die DB? Per O/R-Mapper? Dann schau dass nicht alles in einem "riesen" Kontext kommt (sonst schlägt auch wieder der GC zu).
Wenn du den Importvorgang parallelisieren kannst, so könntest du mit Paralle.Foreach arbeiten. Dort gibt es eine Überladung (ich denke die 13.) mit der mittels localinit und localfinally eine Instanz des O/R-Mapper-Contextes pro Thread erstellt werden kann. Damit könntest du das Problem schon minimieren.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Wird er nur langsamer oder stürzt er dann (nach weiteren 4000) ab?
Gibst du alle Resourcen wieder frei oder behältst du alle Objekte in irgendeiner Art und Weise?
Hallo,
Danke für Eure Antwort. Für den Import in die DB benutze ich typisierte DataSets. Die einzelnen TableAdapter Objekte rufe ich mit "using" auf. Dann ist doch eine Freigabe der Objekte gewährleistet. Oder? Manchmal erhalte ich eine Meldung vom DB-Server, dass der Timeout abgelaufen ist.
ich füge mal bischen Code hinzu.
/// <summary>
/// Die XML Dateien werden importiert
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void btnStartImport_Click(object sender, EventArgs e)
{
// BUTTON
btnStartImport.Enabled = false;
btnCancelImport.Enabled = true;
// Start des asynchronen Vorgangs
bgwImport.RunWorkerAsync();
}
/// <summary>
/// Arbeitsthread gibt einen Fortschritt an.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void bgwImport_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Fortschritt zuweisen
this.pgbStatus.Value = e.ProgressPercentage;
}
/// <summary>
/// Der Worker wurde beendet (erfolgreich, nicht erfolgreich, abgebrochen).
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void bgwImport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Prüfen auf Error
if (e.Error != null)
{
// Error anzeigen
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Message anzeigen
MessageBox.Show("Vorgang durch Benutzer abgebrochen.");
}
else
{
// Message anzeigen
MessageBox.Show("Import-Vorgang abgeschlossen.");
}
}
/// <summary>
/// Vorgang in einem anderen Thread ausführen.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void bgwImport_DoWork(object sender, DoWorkEventArgs e)
{
// Methodenaufruf
e.Result = ImportXmlFilesHelper(bgwImport, e);
}
#endregion
#region Methods
/// <summary>
/// Die Helpermethode bereitet das Importieren die XML-Dateien vor.
/// </summary>
/// <param name="p"></param>
/// <param name="worker"></param>
/// <param name="e"></param>
/// <returns></returns>
private object ImportXmlFilesHelper(BackgroundWorker worker, DoWorkEventArgs e)
{
// List auslesen
foreach (string fileName in this.xmlFileNames)
{
// Methodenaufruf
ImportXml(fileName);
}
return null;
}
private void ImportXml(string fileName)
{
// Objekt erstellen
this.importXmlToSql = new ImportXmlToSql();
// Methodenaufruf
importXmlToSql.ImportXmlData_ToSql(fileName);
// Delegate erstellen und Methodenübergabe
ImportDisplayFileNamesCallback displayFileNames = new ImportDisplayFileNamesCallback(ImportAndDisplayFileNamesInListView);
// Ausführen
this.Invoke(displayFileNames, new object[] { fileName, this.bgwImport });
}
/// <summary>
/// Die XML Dateien werden importiert.
/// </summary>
/// <param name="fileName"></param>
/// <param name="worker"></param>
private void ImportAndDisplayFileNamesInListView(string fileName, BackgroundWorker worker)
{
// INT
int percent = xmlFileNames.Count / 100;
this.fileName = fileName;
// um "1" erhöhen
this.count++;
// Fileane anzeigen
lblFileName.Text = fileName;
// Info anzeigen
lblFile.Text = String.Format("Datei: {0} von {1}", count, this.xmlFileNames.Count);
// Fortschritt anzeigen
lblCount.Text = String.Format("Fortschritt: {0}%", Convert.ToString(this.count / percent));
// ProgessChanged Event auslösen
bgwImport.ReportProgress(this.count / percent);
}
Vielleicht nützt das was.
Mfg
mcpd
Typisierte DataSets sind für so etwas unnötig.
Und wenn du bei den DataAdaptern die Transaction vergessen hast, sind die wirklich sehr langsam.
SqlBulkCopy.WriteToServer-Methode
Wäre hier deutlich schneller.
Hallo mcpd,
ohne dass ich mir den Code angeschaut habe, klingt die Symptombeschreibung grundsätzlich nach Schlemiel the Painter's algorithm oder technischer ausgedrückt, nach quadratischem Aufwand, siehe dazu auch Warum haben WinForms, DataGridView & LINQ eine gute Performance?
herbivore
Hallo mcpd,
ich muss auch öfter mal viele Datensätze importieren (mehrere Tausend bis Millionen).
Mit DataSet einzeln hat das in einem Testfall 36 h gedauert.
Bulkcopy des SQL-Servers : 7 min.
Alle Daten in ein Dataset und dann auf einmal einfügen : 6 h
Dabei teile ich die Daten so auf dass es max. 500 MB im Hauptspeicher belegt.
Probier mal alle oder mehrere Zeilen ins Dataset und dann einfügen.
Ob das Dataset typisiert ist oder nicht sollte keine Rolle spielen.
Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
Hallo mcpd,
das kann viele Ursachen haben. Ich würde zunächst mit Profilern arbeiten und sowohl den Code als auch die Datenbank untersuchen bis du den Farbeimer von Schlemiel gefunden hast.
Welches DBMS nutzt du denn?
Wie komplex sind die XML-Dateien?
Wächst der Hauptspeicherverbrauch kontinuierlich ?
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de