Laden...

OutOfMemory Exception - Arbeitsspeicher voll bei Datenbankexport

Erstellt von casiopeia vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.064 Views
C
casiopeia Themenstarter:in
47 Beiträge seit 2007
vor 13 Jahren
OutOfMemory Exception - Arbeitsspeicher voll bei Datenbankexport

Hallo,

habe ein Tool geschrieben zum exportieren von Daten aus einer Datenbank. Dieses funzt auch wunderbar, jedoch sind es über 300 k Datensätze die zu exportieren sind. Nach etwa 130 k bis 150 k Datensätzen sind vom Prog 1,5 GB Arbeitsspeicher zugewiesen und das prog stürzt ab mit einer OutOfMemory Exception.

Die Daten werden über eine DLL aus der Datenbank serialisiert und über den Streamwriter in eine Datei geschrieben. Der Export erfolgt in einer foreach Schleife, in der keine Variablen deklariert werden, nur initalisiert.

Gruss Casiopeia

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

der Export scheint nicht das Problem zu sein. Wie schaut der Import aus? Wird alles auf einmal geholt? Hier ware "batchweisen" Laden mMn vorteilhafter.

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!"

E
180 Beiträge seit 2010
vor 13 Jahren

klingt auf den ersten blick nach einer unendlichschleife. hast du ma geguckt ob die schleife wirklich ein reales ende hat? habe auch solche funktionen zum einsatz mit den gleichen und höheren Datenmengen und das braucht eigentlich nicht soviel speicher.

haste mal ein codeausschnitt?

C
casiopeia Themenstarter:in
47 Beiträge seit 2007
vor 13 Jahren

@ gfoidl

Hol mir die benötigten Daten mit den IDs und lade diese in einen DataTable. Mit diesen IDs werden die dazugehörigen Informationen ermittelt, sprich erneuter zugriff auf die DB, und dann in ein List<object> gespeichert.

@Equilibrium

es ist keine endlosschleife da es ja auch eine foreach - Schleife ist.
Wieviele Spalten hatten deine Tabelle meine hat über 140 Spalten.

A
69 Beiträge seit 2010
vor 13 Jahren

Die Art und Weise wie du die Daten holst ist falsch. Lade immer nur einen begrenzten Satz an Daten und schreibe diesen in den Stream. Dann hole den nächsten Satz usw..

E
180 Beiträge seit 2010
vor 13 Jahren
re

es ist keine endlosschleife da es ja auch eine foreach - Schleife ist.

hat nicht nur was mit der foreach zutun, kann auch an dem inhalt liegen der innerhalb der foreach verarbeitet wird, aber ohne code ist das schwer zu beurteilen. klingt nur sehr danach, weils typisch für diese art fehler ist.

kannst du ein codeauszug geben? manchmal ist es was absolut banales, was man total übersieht (eigene erfahrung)

A
69 Beiträge seit 2010
vor 13 Jahren

@Equilibrium:

es ist keine Endlosschleife. Die Datenmenge ist das erschlagende. Hier wird ein Dataset mit 300.000 Datensätzen a 140 Spalten befüllt.... da knallt es schon beim einlesen wegen der schieren Anzahl an objekten.

C
casiopeia Themenstarter:in
47 Beiträge seit 2007
vor 13 Jahren

@Arithmetika

Der Export ergibt 140 Spalten nicht der Import der Daten. Geladen werden nur die benötigten IDs um dann die geforderten informationen aus der DB zu fischen und dieser werden in eine List übertragen und dann über den StreamWriter in eine CSV Datei geschriebeb. Die List wird immer wieder neu befüllt und übergeben.

@Equilibrium

hier mal nen zusammengebastelter code snippet 😉

swrTempFile = new StreamWriter(strExportFilePath, false, System.Text.Encoding.Default);
IEnumerable<DataRow> objHotelRowsSelected = objHotelTable.Rows.Cast<DataRow>();
foreach(DataRow objDataRow in objHotelRowsSelected)
{
	objExportList.Clear();
	objExportList.Capacity = objExportTable.Columns.Count;
	for (int i = 0; i < objExportList.Capacity; i++)
		objExportList.Add(null);
			
	strVar1 = string.Empty;
	strVar2 = string.Empty;
	strVar3 = string.Empty;
		
	strVar1 = objExport.Var1
	strVar2 = objExport.Var2;
	strVar3 = objExport.Var3;
		
	objExportList[0] = strVar1;
	objExportList[1] = strVar2;
	objExportList[2] = strVar3;
		
	objDataRowExport =     FillDataRowWithList(objExportTable.NewRow(),objExportList);
		if (null != objDataRowExport)
		{
			for (int i = 0; i < intColumsCount; i++)
			{
				if(objDataRowExport[i] != null)
					swrTempFile.Write('"' + objDataRowExport[i].ToString()   + '"');
				else
					swrTempFile.Write('"' + string.Empty + '"');

				if (i < intColumsCount - 1)
					swrTempFile.Write(";");
			}
			swrTempFile.Write(swrTempFile.NewLine);

		}
}
6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

wie groß ist der Wert bei

objExportList.Capacity = objExportTable.Columns.Count;

denn dort wird die List<T> (?) auf die Größe gesetzt.

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!"

C
casiopeia Themenstarter:in
47 Beiträge seit 2007
vor 13 Jahren

144 , dies entspricht der Anzahl der Spalten des Exports

4.939 Beiträge seit 2008
vor 13 Jahren

Hallo,

aus dem Code-Snippet kann man keinen konkreten Fehler erkennen.
Am besten, du benutzt einen Memory-Profiler, z.B. http://memprofiler.com/ (als Trial zum Download).
Der kann dir dann am besten sagen, wo du Speicherlecks hast (z.B. fehlende Dispose() bzw. using-Anweisungen).

V
162 Beiträge seit 2010
vor 13 Jahren

Hi,

ich hab nicht so viel gemacht mit StreamWritern.
Schau doch mal: TextWriter.Flush-Methode
Wird der Reserviertespeicher vom Stream nicht durch Flush/AutoFlush frei?

MfG
Björn

Das Leben ist schön!

3.825 Beiträge seit 2006
vor 13 Jahren

Ich würde das Lesen der Daten aus der Datenbank nicht per Dataset / Datatable sondern per DataReader vornehmen.

Braucht kaum Speicher, geht schneller und der Anwender kann den Exportvorgang auch abbrechen wenn er länger dauern sollte.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3