![]() |
Datenbank: Firebird embedded • Version: 2.1 • Zugriff über: per TSQLQuery
Firebird Import aus Textdatei extrem langsam
Hallo zusammen!
Ich habe ein massives Problem beim Import von Daten aus einer Textdatei in eine Firebird-DB. Die Laufzeit ist schlicht und einfach katastrophal. Für je 100 Datensätze mit gerade mal 5 lumpigen Textfeldern benötigt das Programm ca. 1 Sekunde. Macht bei ca. 110000 Datensätzen also 1100 Sekunden bzw. fast 20 Minuten. Das Lesen der Daten inkl. Split der einzutragenden Felder sowie Aufbau eines passenden INSERT-Statements benötigt gerade mal 32 Sekunden. Die gesamte Zeit scheint daher alleine von einem einzigen SQL-Statement pro Satz aufgefressen zu werden. Woran kann das liegen? Wäre für jede Idee dankbar ... Gruß globetrotter77 |
Re: Firebird Import aus Textdatei extrem langsam
oder ist das etwa normal, dass es so lange dauert?
liegt es an Firebird oder an der TSQLQuery-Komponente? in der vorherigen Version habe ich noch mit der leider ja hoffnungslos veralteten BDE gearbeitet und durchaus vernünftige Laufzeiten erreicht. hat jemand Erfahrung mit Datenimport in Firebird? wie macht man's geschickterweise? und richtig schnell? |
Re: Firebird Import aus Textdatei extrem langsam
Was ist TSqlQuery ? :shock: Faktor 10-100 ist allerdings nicht ungewöhnlich, sofern WinApi Funktionen verwendet werden. Memo, Listbox, Stringgrid etc. Die Aktualisierung / Anzeige dauert da ewig. 8)
|
Re: Firebird Import aus Textdatei extrem langsam
ist schon klar, dass manche Funktionen ewig dauern, aber bei ist der Unterschied tatsächlich reduzierbar auf die Ein-/Ausblendung von
Delphi-Quellcode:
Gibt es eine andere Komponente, mit der man direkte SQL-Statements abgeben kann?with DM_User.SQLQueryTemp do begin with SQL do begin Clear; Add(sqltxt); end; ExecSQL(true); end; Ich gebe zu, dass ich mich da nicht besonders auskenne ... habe früher immer die BDE und Paradox benutzt und war eigentlich immer zufrieden ... nachdem die aber mittlerweile so richtig veraltet ist, wollte ich mal anders rangehen ... leider nur mit mässigem Erfolg |
Re: Firebird Import aus Textdatei extrem langsam
Kombination von Clear und Add ist schon gut. :mrgreen:
|
Re: Firebird Import aus Textdatei extrem langsam
Vielleicht hilft dir ja...
Code:
weiter.
CREATE TABLE tabelle EXTERNAL FILE 'file.txt' (...);
Add: Oder du baust dir ein SQL-Statement, dass alle INSERTs auf einmal durchführt...
SQL-Code:
INSERT INTO tabelle
SELECT FIRST 1 feld1, feld2, ... FROM tabelle UNION SELECT FIRST 1 feld1, feld2, ... FROM tabelle : : |
Re: Firebird Import aus Textdatei extrem langsam
über external file habe ich auch schon nachgedacht, aber ich habe das Problem, dass ich davon ausgehen muss, dass doppelte Schlüssel vorkommen ... wie geht der Import via external file damit um?
im Augenblick löse ich das durch ein try-except-Konstrukt ... und wie definiere ich in einem external file Datumswerte? hat jemand Erfahrung? |
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
Mach es so...
Delphi-Quellcode:
SQLQueryTemp.SQL.Text:=sqltxt;
SQLQueryTemp.ExecSQL(true); Zitat:
SQL-Code:
...und mache danach einen Import in eine andere Tabelle...
CREATE TABLE tabelle EXTERNAL FILE 'file.txt' (feld1 INT, feld2 CHAR(10));
SQL-Code:
Da hier die Feldinhalte eine konstante Größe (mit Leerzeichen gefüllt) haben müssen, kannst du in diesem Schritt auch gleich die Zeichenketten trimmen.
INSERT INTO richtige_tabelle
SELECT DISTINCT feld1, TRIM(feld2) FROM tabelle Zitat:
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
Zitat:
Zitat:
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
Zitat:
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
wie meinst du das? |
Re: Firebird Import aus Textdatei extrem langsam
Wenn die Daten in der Datenbank sind, kannst du sie doch wesentlich einfacher per SQL formen, weiterverarbeiten und analysieren, als wenn du alles selber programmieren musst. Der Aufwand entfällt dann und du kannst alles über einfaches SQL lösen.
|
Re: Firebird Import aus Textdatei extrem langsam
So, ich habe das jetzt mal selber ausprobiert...
Code:
Also für einen Datensatz ca. 18µs (auf meiner Maschine = P4, 3GHz)
1.000.000 Zeilen = 0:18 (Datei = 16MB)
1.000.000.0 Zeilen = 2:48 (Datei = 166MB) |
Re: Firebird Import aus Textdatei extrem langsam
Delphi-Quellcode:
Ich würde die Query nur einmal zu Beginn des Einlesens erzeugen und den SQL-Text zuweisen, dabei dann mit Parametern arbeiten:with DM_User.SQLQueryTemp do begin with SQL do begin Clear; Add(sqltxt); end; ExecSQL(true); end;
SQL-Code:
In der Einleseschleife dann die Parameter zuweisen und ExecSQL aufrufen. Vorteil: die Query wird vom Server nur einmal erzeugt und dann für jedes Insert wiederverwendet. ("Prepared Statement").
insert into tabelle(f1, f2, f3, ...) values (:f1, :f2, :f3, ...)
Eventuell hilft es auch noch, die ganze Sache in einer Transaktion laufen zu lassen. Viele Grüße, |
Re: Firebird Import aus Textdatei extrem langsam
Und eine explizite Transaktionssteuerung verwenden. Denn sonst wird dank autocommit jeder Insert insert in eine eigene Transkation gepackt.
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
und wie macht man das mit der expliziten Transaktionssteuerung? |
Re: Firebird Import aus Textdatei extrem langsam
Mit dbExpress kenne ich mich nicht aus, aber versuche mal
SQLConnection.StartTransaction() und SQLConnection.Commit() |
Re: Firebird Import aus Textdatei extrem langsam
StartTransaction erwartet einen "benutzerdefinierten Transaktionsbezeichner" - was ist denn damit gemeint??
und wie macht man das? |
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
wie war das nochmal mit den Params? wie ordne ich denen Werte zu? geht das mit
Delphi-Quellcode:
und muss ich das Prepare selbst auslösen?
SQLQuery.Params[0].Value:='blabla';
|
Re: Firebird Import aus Textdatei extrem langsam
Hallo,
hast Du schonmal probiert, was passiert, wenn Du mehrere Insert gleichzeitig absetzt? Davon ausgehend, dass das in einer Schleife passiert:
Delphi-Quellcode:
einmal in der Art ändern:
with DM_User.SQLQueryTemp do
begin with SQL do begin Clear; Add(sqltxt); end; ExecSQL(true); end;
Delphi-Quellcode:
dann wird alle 100 Datensätze das Insert für diese Sätze abgesetzt. Bei der 100 kannst Du dann auch ausprobieren, ob eine größere oder kleinere Anzahl von Sätzen die Geschwindigkeit erhöht oder verringert.
DM_User.SQLQueryTemp.Sql.Clear;
... // irgendeine Schleife with DM_User.SQLQueryTemp do begin SQL.Add(sqltxt); If SQL.Count Mod 100 = 0 then begin ExecSQL(true); SQL.Clear; end; end; ... // Ende der Schleife // Hier nicht vergessen den Rest wegzuschreiben, wenn die Satzzahl nicht durch 100 zu teilen ist. If DM_User.SQLQueryTemp.SQL.Count > 0 then DM_User.SQLQueryTemp.SQL.ExecSQL(true); Wie sieht der Indexaufbau der Tabelle aus, auch hier kann bei satzweisem Einfügen ein Laufzeitproblem auftreten, wenn die Pflege des Index zu kompiliziert wird. Eventuell auch den Index vor dem Import wegwerfen und nach dem Import neuerstellen, dies geht allerdings nur, wenn der Index nicht zur Doppeltenprüfung... benötigt wird. |
Re: Firebird Import aus Textdatei extrem langsam
langsam, aber sicher, glaube ich, nicht mehr programmieren zu können!
beim Versuch, mit Params zu arbeiten, bekomme ich jetzt bei jeder Zeile folgenden Fehler: Datenbank-Server-Fehler: Column unknown ARTNR At line 1, column 38 das SQL-Statement habe ich auf das Minimum gekürzt:
SQL-Code:
Sehr seltsam, da er die ARTNR in der Feldliste offenbar sehr wohl kennt, erst in der Werteliste passt es ihm nicht mehr!!!
INSERT INTO ARTIKEL (ARTNR) VALUES (:ARTNR)
|
Re: Firebird Import aus Textdatei extrem langsam
Hallo,
zeig' uns bitte mal den Quelltext, mit dem Du die Parameter füllst, da scheint irgendetwas schief zu laufen. Mir sieht das so aus, als würden der Parameter nicht gefüllt werden. |
Re: Firebird Import aus Textdatei extrem langsam
Delphi-Quellcode:
nicht wundern über den veränderten Namen, ich habe fürs Testen einen neuen SQLQuery angelegt.
DM_User.SQLQueryImport.Params[paramnr].Value:=feldtxt;
Der Parameter ist definiert mit
Delphi-Quellcode:
DataType = ftString
Name = 'artnr' ParamType = ptInput Size = 17 Value = '' |
Re: Firebird Import aus Textdatei extrem langsam
Hallo,
was Du gemachts hast, sieht eigentlich nicht wirklich falsch aus, daher hier mal ein paar Vorschläge zur Lösung des Rätsels: Sind Datenbank und/oder Komponenten bei den Tabellen-, Feld- und/oder Parameternamen casesensitive? Schreib' mal in den Statements alle Tabellen- und Spaltennamen genau so, wie die Datenbank. Ebenso die Parameternamen im Statement so, wie Du sie im Programm definiert hast. Was steht in paramnr? Bist Du sicher, das Du da den richtigen Parameter erwischst? Kannst Du das im Programm auch mit ParamByName oder ähnlichem umsetzen? |
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
Delphi-Quellcode:
var TD:TTransactionDesc; (aus DBXpress)
begin SQLConnection.StartTransaction(TD); try SQLConnection.ExecuteDirect('INSERT INTO ...'); SQLConnection.Commit(TD); except SQLConnection.Rollback(TD); end; end; |
Re: Firebird Import aus Textdatei extrem langsam
da bin ich mir sogar sehr sicher, weil ich nämlich nach dem Zurechtstutzen auf das Wesentliche versehentlich noch einen anderen Parameter füllen wollte, der in der Abfrage gar nicht mehr vorkommt - das führt sofort zu einem Systemfehler!
Andererseits führt auch die konsequente Verwendung der Kleinschreibung beim Parameter immer zur selben Fehlermeldung mit groß geschriebener ARTNR. ParamByName etc. habe ich auch ausprobiert - keine Veränderung bin langsam mit meinem Latein am Ende ... :( |
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
"Ungültige Transaktions-ID" Wie kann man die ID zuordnen? Ich hätte eigentlich gedacht, dass das die DB für mich übernimmt, oder? |
Re: Firebird Import aus Textdatei extrem langsam
Oh, den Fehler hatte ich noch nie. TD ist aber nur ein einfaches Record. Einfach mal TD. eingeben...
|
Re: Firebird Import aus Textdatei extrem langsam
|
Re: Firebird Import aus Textdatei extrem langsam
sehr schön, wenn auch unverständlich:
mit StartTransaction(TD) und Commit(TD) geht's plötzlich einigermaßen schnell. Vorher ist allerdings noch TD.TransactionID:=1; erforderlich. Ca. 105000 Datensätze in knapp 4 Minuten Kein Vergleich mit dem Ergebnis von omata, aber immerhin. Allerdings dauert danach ein Open eines ClientDataSets schlappe 15 (fünfzehn!) Minuten!!! Abgesehen davon, dass es für mich nach wie vor unverständlich bleibt, wieso es a) über ein ClientDataSet ewig lange dauert b) mit Hilfe von SQLQuery nicht möglich ist bzw. unverständliche Fehlermeldungen liefert ist es natürlich völlig unzumutbar für den User, nach dem Datenimport so lange zu warten, bis sich wieder was tut. Wo ist denn hier der Fallstrick versteckt? Ich kapiere es nicht mehr! Wie gesagt - mit BDE und Interbase-Komponenten war das alles überhaupt kein Problem. Wo kann ich denn bei den Einstellungen überhaupt so nen Bock schießen? Ich gehe zumindest mal davon aus, dass ich ihn selber geschossen habe ... |
Re: Firebird Import aus Textdatei extrem langsam
Hallo,
benutzt du denn jetzt das hier ?
Delphi-Quellcode:
Du musst das mit den Parametern und der Query hinbekommen.
var
TD:TTransactionDesc; (aus DBXpress) begin TD. // usw. SQLConnection.StartTransaction(TD); try SQLConnection.ExecuteDirect('INSERT INTO ...'); SQLConnection.Commit(TD); except SQLConnection.Rollback(TD); end; end; Eine prepared Query ist etwa doppelt so schnell wie das da oben. Man könnte auch noch folgendes machen: - je nach 500 Datensätzen Commit/StartTransaction - per Alter Index XXX Inactive alle nicht benötigten Indizes deaktivieren Heiko |
Re: Firebird Import aus Textdatei extrem langsam
Oder alles in Kombination.
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
Das werde ich noch abändern. Pro Datensatz ist allerdings auch zu langsam. Zitat:
Oder wäre es möglich, innerhalb von SQLConnection.StartTransaction und SQLConnection.Commit wieder auf SQLQuery-Methoden zurückzugreifen? (Mal abgesehen davon, dass die unbekannte Spalte angemeckert wird) Zitat:
Zitat:
Leider hat das alles aber gar nichts damit zu tun, dass sich das System danach (!) völlig unzumutbar verhält. |
Re: Firebird Import aus Textdatei extrem langsam
Hallo,
Zitat:
Was passiert, wenn du den Server-Dienst (FBGuardian) anhälst und neustartest ? Ist es danach wieder "normal" schnell, dann hast du eine offene Transaktion (also eine nicht comittete). Zur Query. Was war noch mal das Problem, nicht die SQLQuery zu benutzen ? Wie weit warst du denn da schon. Hast du noch den Quellcode davon (nicht nur die Splitter hier) ? Heiko |
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
Zitat:
Zitat:
den Quellcode habe ich mittlerweile so sehr gemetzelt, das er kaum noch zu erkennen ist, nur um die verschiedenen Vorschläge auszuprobieren. ich habe den Eindruck, dass ich ein grundsätzliches Einstellungsproblem vorliegen habe, habe aber leider keine Ahnung, wo das liegen könnte. was mir ohnehin nicht gefällt, ist die Verwendung der dbExpress-Komponenten (sind mir schon wegen der Unidirektionalität sehr suspekt), aber ich wüsste nicht, was ich sonst nehmen könnte. wenn ich es richtig in Erinnerung habe, muss ich das ClientDataSet verwenden, um auch rückwärts gehen zu können, nicht wahr? irgendwie zieht hier eine Krücke die nächste nach sich, und diese gleich noch mal eine usw. usw. Was für Connection-Möglichkeiten gibt es denn sonst noch? und ist da auch was Empfehlenswertes dabei? |
Re: Firebird Import aus Textdatei extrem langsam
Hallo,
wie wäre es mit den Zeos-Komponenten? ![]() ![]() ![]() Beim ClientDataSet darfst Du nicht vergessen, dass er die gesamten Daten im Arbeitsspeicher vorhält, Deine 100 und ein paartausend Sätze werden also erstmal in die Arbeitsspeicher geladen, ist das erforderlich, da ja offensichtlich eine ziemlich arge "Spassbremse". |
Re: Firebird Import aus Textdatei extrem langsam
Hierfür sollte auch IBX ausreichen
|
Re: Firebird Import aus Textdatei extrem langsam
|
Re: Firebird Import aus Textdatei extrem langsam
Zitat:
könntest du mir vielleicht mal verraten, welche Komponenten und Methoden du verwendet hast? evtl. den Quelltext und/oder die Einstellungen im Object Inspector? vielleicht komme ich dann dahinter, was ich falsch gemacht habe ... wäre toll! Edit: hast du auch doppelte Primary Keys dabei? die muss ich nämlich berücksichtigen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:06 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 by Thomas Breitkreuz