sequentielle verarbeitung (pumpen vom Daten) wird immer langsamer

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
Hamburgo
Beiträge: 120
Registriert: Di 28. Mai 2019, 17:28

Hallo zusammen,

ich bin gerade dabei meine größte Tabelle von ISO nach UTF8 zu konvertieren,
also von einer ISO-DB in eine UTF8-DB zu pumpen. Umgebung: PHP unter Apache.

Die Tabelle hat 1.087.786 Datensätze, die sequentiell in die neue DB übertragen
werden, wobei ALLE Indizes in Ziel-DB vorher IN-aktiv gesetzt wurden.

Die ersten 50.000 Datensätze wurden noch mit einer Geschwindigkeit von 1.000
in ca. 2 Minuten gepumpt.

Nun bin ich bei bei ca. 250.000 Datensätzen und für 1.000 Datensätze brauch es
inzwischen gut 8 Minuten, also eine Verlangsamung um Faktor 4 mit weiter steigender
Tendenz.

Das bei zunehmender Größe der Ziel-Tabelle das Ganze ein wenig langsamer wird,
wäre ja noch zu akzeptieren, aber dass es so eklatant langsamer wird, verstehe ich
nicht so recht.

Es werden doch nur weitere Datensätze hinten dran geklatscht, ohne das Indizes
oder sonst irgendetwas nach-gepflegt werden müsste.

Wofür verbraucht Firebird diese viele Mehr-Zeit ?

Hat jemand eine Erklärung ?

Kann ich etwas machen, um da mehr Tempo rein zu bringen ?
Benutzeravatar
martin.koeditz
Beiträge: 377
Registriert: Sa 31. Mär 2018, 14:35

Hallo Hamburgo,

nutzt du vielleicht irgendeine Art von Vergleich während des Pumpens? Oder wird zusätzlich ein Trigger ausgeführt? Dann fehlt vermutlich nur ein Index.
Ist kein Index vorhanden, werden die Tabellen sequenziell durchlaufen. Dann dauert die Suche mit zunehmender Größe immer länger. Die Index-Daten stehen bestenfalls im Arbeitsspeicher.

Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 388
Registriert: Mo 7. Mai 2018, 18:09

Einen solchen Effekt konnte ich bisher noch nie feststellen.
Bei korrekter Verwendung der SQL-Möglichkeiten kann man konstant, je nach Zeilenlänge 1000 bis 4000 Inserts/Sekunde erreichen.
Wichitg sind dabei aber:

Der SQL-String für den Insert muss mit Parametern erfolgen.
Also

insert into mytable (f1, f2, f3, .... fn) values(?, ?, ?,...?)

Für jedes ? gibt es dann einen Parameter.
Parameter werden von den FB-Treibern i.d.R. unterstützt.
Ich verwende hierfür alternativ den ODBC-Treiber bzw. den C# Firebirdclient.

Vorteile:
Der SQL wird nur 1x analysiert und steht dann direkt als "ausführbar" zur Verfügung.
Jeder Parameter ist typisiert. Also einen Cast für den Zieltyp der DB braucht es dann nicht.
Die Parameterobjekte lassen sich leichter füllen als eine Stringaufbereitung für jeden Insert.

Nachteile:
Keine!

Dies gilt i.Ü. für (fast) jede Datenbank.
Klar, für JSON/XML-Objekte gilt das leider nicht, die müssen stringifiziert werden.

Prüfe also mal genau, was du tust. Und ob du nicht ggf. Daten im Programmspeicher zwischenpufferst und nur der Hauptspeicher nicht mehr ausreicht und dieser dann über die Platte ausgelagert wird (Taskmanager->Details->Arbeitspeicher).
Antworten