![]() |
Datenbank: Interbase • Version: V6.1 • Zugriff über: InterbaseExpress
Viele Datensätze Updaten / vergelichen
Hallo leibe Delphianer,
ich muß hier etlich Datensätze vergeleiche bzw. aufbereiten updaten. Die Daten werden im CSV Format geliefert. Als erstes übertrage ich die Daten mal in eine Interbase Datei. Dieses Daten sollen nun umgewandelt bzw. mit Daten in eiener anderen Interbase DB verglichen werden. Es handelt sich um ca. 700.000 Datensätze. Ich bekomme immer nach ca. 70.000 Datensätze eine Fehlermeldung, das zu wenige Arbeitsspeicher vorhanden ist und das auf einem Server mit 8 GB Ram. Ich denke mal, das ich ein Fehler in meinen Programm habe welche ich einfach nicht finden kann. Ich habe mal den Code auf das nötigste gekürzt und hoffe, das mir hier jemand helfen kann. Es sein den Speicher nicht mehr freizugeben Zuerst mal die Komponenten SucheDaten1,SucheDaten,SucheDaten3,KanalSuchen sind TIBQuery´s BearbeiteDaten1 ist eine TIBDataset Ich habe hier schon einiges versucht wie z.B. ein Commit auf die Datenabk nach ca. 10.000 Datensätzen. Nur gebracht hat bis jetzt alles noch nicht.
Delphi-Quellcode:
procedure TPPusKanalEinlesen.DatenEinlesen;
var I: Integer; FehlerZaehler: integer; Kanal: string; HKanal1,HKanal2,HKanal3: string; KanalZahl: integer; Zaehler: integer; begin Daten.SucheDaten1.Prepare; Daten.SucheDaten2.Prepare; Daten.SucheDaten3.Prepare; Daten.BearbeiteDaten1.Prepare; Daten.AnfangsDaten.Active := False; Daten.AnfangsDaten.Active := True; Daten.AnfangsDaten.First; While not Daten.AnfangsDaten.Eof do begin Daten.SucheDaten1.ParamByName('Wert1').AsSTring := Daten.AnfangsDaten.FieldByNAme('Wert1').AsString; Daten.SucheDaten1.Active := True; Daten.SucheDaten2.ParamByName('Wert2').AsSTring := Daten.AnfangsDaten.FieldByNAme('Wert2').AsString; Daten.SucheDaten2.Active := True; if (Daten.SucheDaten1.RecordCount > 0) and (Daten.SucheDaten2.RecordCount > 0 ) then begin Daten.BearbeiteDaten1.ParamByName('Test1').AsString := Daten.SucheDaten2.FieldByName('Test1').AsString; Daten.BearbeiteDaten1.ParamByName('Test2').AsString := Daten.SucheDaten1.FieldByName('Test2').AsString; Daten.BearbeiteDaten1.Active := True; if Daten.BearbeiteDaten1.RecordCount > 0 then begin //Wurde gefunden if Daten.BearbeiteDaten1.FieldByName('Kanal').AsString = '' then begin //Es ist bis jetzt noch kein Kanal angegeben. Daten.BearbeiteDaten1.Edit; //Hier wird noch etwas andres gemaucht habe ich jedoch gelöscht da unwichtig Daten.BearbeiteDaten1.FieldByName('TestDatum').AsString := DateToStr(AktuellesDatum); Daten.BearbeiteDaten1.Post; end else begin if Daten.BearbeiteDaten1.FieldByName('Kanal').AsString <> Kanal then begin Daten.BearbeiteDaten1.Edit; //Hier wird noch etwas andres gemaucht habe ich jedoch gelöscht da unwichtig Daten.BearbeiteDaten1.FieldByName('TestDatum').AsString := DateToStr(AktuellesDatum); Daten.BearbeiteDaten1.Post; end; end; end else begin FehlerZaehler := FehlerZaehler +1; Fehler.Caption := IntToStr(FehlerZaehler); end; end else begin FehlerZaehler := FehlerZaehler +1; Fehler.Caption := IntToStr(FehlerZaehler); end; Daten.AnfangsDaten.Next; end; Daten.TransEdit.Commit; end; |
Re: Viele Datensätze Updaten / vergelichen
Hallo Tanja,
dein Hauptspeicherproblem kann ich nicht entdecken, aber die Performanz sollte so nicht sehr berauschend sein. Du solltest prüfen, warum du neben IBDataSet noch IBQuery verwendest, eine Komponente die eher als Migrationshilfe für BDE-Anwendungen konzipiert ist. Das Commit sieht irgendwie unmotiviert aus, so ganz ohne StartTransaction. Ich vermute, dass sich ein Großteil der Aufgaben durch eine Implementierung in SQL Procedure Language erledigen lässt - ohne Speicher- und Performanzprobleme - zumal du die Daten ja bereits in die Datenbank geladen hast. Wenn du weitermachen willst wie bisher, dann solltest du vielleicht ein paar Prüfpunkte in deinen Code aufnehmen. Auf diese Weise kannst du herausfinden, wie sich der Speicherverbrauch zwischen signifikanten Code-Blöcken entwickelt und ob er in Schleifen ansteigt. Oder ist das Laden der CSV-Daten über StringList erfolgt und due hast diese Listen nicht freigegeben? Grüße vom marabu |
Re: Viele Datensätze Updaten / vergelichen
Ich vermute das der hohe Speicherverbrauch an dern impliziten Tranaktionssteuerung der Komponenten liegt.
|
Re: Viele Datensätze Updaten / vergelichen
Zitat:
ich kann es auch nicht verstehen wo das Problem mit dem Speicher sein soll. Aus Verzweiflung habe ich nun bei jedem Post ein Commit gemacht. Danze ist nun noch langsamer, aber wegen mir kann es eine Tag bei der ersten Version laufen hauptsage es geht. Leider geht das auch nicht. IBQuery habe ich benutzt um ID´s aus zwei verschieden Tabellen zu bekommen und herrauszufinden, wenn eine Datsatz nicht vorhanden ist, in welcher der zwei Tabellen es fehlt. In der Dritten Tabelle sind die nur die ID´s der beiden Tabellen vorhanden. An eine Stored prodedure habe ich auch schon mal gedacht, jedoch wird es vermutlich nicht gehen. In einen Feld steht ein Sting, welches ich "zerlegen" muß und je nachden was dort drin steht eine Zahl einfügen. Dazu habe ich die Funktionen Pos,copy und Case of von Delphi benutzt. An die Prüfpunkte habe ich auch schon mal gedacht, jedoch ob mich das weiterbingt weiß ich auch nicht. Das Problem ist ja bei diesem Code dauert es etlich Zeit, bis es 70.000 Datensätze verarbeitet hat und der Fehler kommt. Das Programm besteht nur aus dieser Schleife. Die CSV Datei habe ich mittels Databump übertragen. Das war auch das einzige was funktioniert hat. Ich beschreibe Dir mal den Aufbau des Files und der Tabellen File: Feld1,Fled2,Fled3 Mittels des Feld1 wird eine ID aus der ersten Tabelle geholt Mittels des Feld2 wird eine ID aus der zweiten Tabelle geholt In der dritten Tabelle steht nur die ID von Fled1 und Feld2 drin. Des weitern Gibt es ein Feld in den ich einen Zahl eintragen möchte und ein Feld in welches in das aktuelles Datum eintragen möchte. Die zahl muß wie oben beschrieben noch berechnet werden. Hast du so etwas schon mal mit einer Stored Procedure erledigt ? Wie lange würde es bei einer Stored Prodeure denn Dauern bei ca. 750.000 Datensätze ? Tanja |
Re: Viele Datensätze Updaten / vergelichen
Hallo Tanja,
der Grundstein einer guten Lösung ist eine exakte Problembeschreibung - jedenfalls kann die Qualität der Lösung nicht besser sein als die Qualität der Analyse. Oft ist ein deklarativer Ansatz besser als ein prozeduraler, ganz besonders wenn SQL im Spiel ist. In deinen Beiträgen erkenne ich die Tabelle Anfangsdaten A (Wert1, Wert2, ...), zwei Tabellen mit Suchdaten S1 (Test1, Wert1, ...) und S2 (Test2, Wert2, ...), sowie die Tabelle Bearbeitungsdaten B (Test1, Test2, Kanal, TestDatum, ...). Du hast offensichtlich eine ein-eindeutige Schlüsselabbildung von A.Wert1 nach B.Test1 über S1, wodurch S1.Wert1 neben dem primary key S1.Test1 zum candidate key avanciert. Analoges gilt für S2. Andernfalls könntest du nicht wie gezeigt suchen. Für jedes Tupel (A.Wert1, A.Wert2) suchst du ein korrespondierendes Tupel (B.Test1, B.Test2) um bei dessen Existenz einige Felder (B.TestDatum) in Abhängigkeit einer Funktion K(B.Kanal, ...) zu verändern. Die Funktion K() hast du nicht genau beschrieben. Wenn es sich dabei nur um verkettete String-Funktionen handelt, dann ist eine Implementierung in SQL sehr wahrscheinlich möglich. In meinem Beispiel habe ich K() als Null-Test eingesetzt:
SQL-Code:
Reverse Engineering ist nicht einfach. Wenn ich deine Anforderungen nicht richtig erkannt habe, dann kannst du sie gerne etwas präzisieren.
UPDATE B
SET TestDatum = '2007-07-16' WHERE Kanal IS NULL AND EXISTS ( SELECT B.* FROM A, B, S1, S2 WHERE A.Wert1 = S1.Wert1 AND A.Wert2 = S2.Wert2 AND S1.Test1 = B.Test1 AND S2.Test2 = B.Test2 ) Freundliche Grüße |
Re: Viele Datensätze Updaten / vergelichen
Hallo,
mir fällt noch ein: - RecordCount ersetzen durch Select Count(*) (mit sqlmonitor mal prüfen) - alles auf Unidirectional=true setzen - mal die Speicherbelegung im Taskmanager verfolgen - try finally bei Active=True ich sehe nirgendwo ein Active False ? - memcheck nehmen und mal nur 1000 Einträge nehmen Heiko |
Re: Viele Datensätze Updaten / vergelichen
Hallo Heiko,
bei einem Existenztest würde ich DataSet.IsEmpty prüfen - die Umstellung auf eine Zählung macht für mich nur Sinn, wenn eine großes Resultset zu befürchten wäre. Wenn Tanja bei ihrem prozeduralen Code bleiben möchte, dann sind auch noch ein paar andere Dinge zu reparieren. Zum Beispiel wird der FehlerZaehler nie initialisiert. Ich kann mir aber nicht vorstellen, dass diese Lösung in Produktion gehen wird: 700.000 Aufrufe für Query.Open (Close fehlt im gezeigten Code) dürften den Job zu einem echten Langläufer machen. Vor allem wenn keine passenden Indexe eingerichtet wurden. Freundliche Grüße |
Re: Viele Datensätze Updaten / vergelichen
Korrekt,
deshalb wird jede meiner Queries durch den ibplanalyzer geschickt. Tanja: Warum packst du die 750000 CSV-Dateien nicht schon "ent-csv"'1 in eine Hilfstabelle, mache noch ne id als autoinc (trigger) rein, dann kannst du schnell mal mit "kleiner Tabelle" testen. Die SP muss sich dann nicht mit String-Operationen rumärgern. Ich würde auch erst mal rausfinden, ob das Programm (memcheck) oder Interbase (task-manager) den Fehler bringen. Heiko |
Re: Viele Datensätze Updaten / vergelichen
Man könnte auch versuchen die CSV als external file einzubinden. Dadurch kann man diese wie eine Tabelle verwenden.
|
Re: Viele Datensätze Updaten / vergelichen
Durch die die könnte man die Dateien schneller leeren,
ginge natürlich auch, wenn man vor dem Import mal "ein paar" Zeile der csb löscht... Heiko |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz