Einzelnen Beitrag anzeigen

Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.534 Beiträge
 
Delphi 11 Alexandria
 
#1

Kodieren gegen großes Datenvolumen (Datendatei > 2 GB, > 15 Mio. DS)

  Alt 5. Apr 2019, 20:49
Nun habe ich ein Update von meinem (einfachen) Datenbank-Programm fertig gestellt (keine große Nummer, eher für einfache Aufgaben und wenig Datenvolumen gedacht). Sollte vorab vielleicht erwähnen, dass ich hier alle Daten im Speicher halte (Stringlisten) und keine besondere Daten-Engine verwende.

Eigentlich wollte ich letzte Woche "nur" mal testen, wie viel Datensätze das Programm aus einer csv-Datei importieren kann (das hat das Release dann noch ein paar Tage verzögert...).

Einige 10.000 oder 100.000 ging ja schon vorher, aber wie steht es mit Mio.Datensätzen?

Der erste Versuch, eine 170 MB große Datendatei mit ca. 2,1 Mio. DS zu importieren (in der Windows 32-Bit-Version) scheiterte kläglich an mangelndem Arbeitsspeicher.

OK, da kann man ja noch was optimieren. Den Stream brauch ich doch an Stelle X gar nicht mehr, also warum erst warten mit der Freigabe bis Stelle y, usw...

Die Daten werden in einen Stream eingelesen, der auf bestimmte Dinge überprüft wird und anschließend über eine Stringlist in mein Datenbank-Endformat gebracht (das z.B. aus der 170 MB-Datei dann eine nur noch 70 MB große Datei macht).

Was mir dabei auffiel - und mir jedenfalls nicht bewusst war - welche einfachen "bequemen" Dinge doch viel Arbeitsspeicher kosten:

Ein "if (pos '/sb', slData.text) <> 0" veranlasst Delphi, für (sldata.text) einen extra String zu bauen, der noch mal richtig schön Arbeitsspeicher braucht. Für kleine Datenmengen kein Problem, aber wenn man mehrere 100 MB geladen hat, schon.

Also lieber zeilenweise durch die Liste iterieren und nach dem Teil suchen.

Soweit habe ich das dann tatsächlich hinbekommen, dass ich in der 32-Bit-Version die 2,1 Mio. DS importieren und anzeigen lassen kann (schnell ist das Programm aber dann nicht mehr, in der allgemeinen Anzeige schon, aber in der Filterung von DS nicht, dazu später). Zur Erinnerung: Eine 32-Bit-Version kann nicht mehr als 2 GB Arbeitsspeicher in Anspruch nehmen.

OK und wie viele DS kann das Programm dann in einer 64-Bit-Version laden?

Eine große Datendatei zum freien Download habe ich hier gefunden: https://sdm.lbl.gov/fastbit/data/samples.html

Eben die 2 GB-Datei mit 15 Mio. Datensätzen.

Aber auch hier scheiterte erst mal der Datenimport, weil die Stringliste nicht optimal arbeitet, wenn ein Encoding (UTF-8) auf den Stream angewendet werden soll.

Hier half mir ein Tipp von Uwe (https://www.delphipraxis.net/1316866-post22.html), den ich für meine Bedürfnisse angepasst habe, so dass ich also auch die 2 GB in die Stringliste reinladen kann.

Interessanterweise benötigt die eingelesene Stringliste das 3-4 Fache an Arbeitsspeicher.

Hier fangen meine Fragen an:

* Warum eigentlich? UTF8- ist ja nicht gleich Größe mal zwei sondern eher Größe und ein wenig dazu.
* Gibt es Delphi-Interne Alternativen zur Stringliste (um die Daten zu halten), bzw. externe Lösungen, die nicht soviel Speicher verbrauchen?
* Die Sortierung (mit bis zu 3 keys) mache ich derzeit auch über eine Stringliste, eine TDictionary (das verwende ich für den Primärkey je Tabelle) hilft da nicht weiter, da ich ja nicht doppelte Einträge aufnehmen kann. Gibt es andere schnelle Alternativen für Sotierungen (mit mehreren Schlüsseln)?

Geändert von Harry Stahl ( 5. Apr 2019 um 20:59 Uhr)
  Mit Zitat antworten Zitat