[gelöst] DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Helios
Lazarusforum e. V.
Beiträge: 93
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.2.0 Windows 10 64Bit / Lazarus 2.0.12 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Helios »

Hallo Soner,
hallo wp_xyz,

@Soner: Leider kann ich die 2 Sekunden Abfragezeit mit dem Lösungsansatz "SQLQuery1.Last nach SQLQuery1.Open" nicht bestätigen. Schade, das wäre eine schöne Lösung gewesen.
Mit wie vielen Zeilen hast Du dieses Testergebnis erzielt?
Hast Du evtl. noch eine andere Einstellung im Vergleich zu meinem Beispielprojekt oben gesetzt gehabt?
Ich verwende Windows 10, 64Bit mit Lazarus 2.0.12 (64Bit) und Firebird 3.0.7 (64Bit). Bei 100.000 Zeilen dauert das Befüllen des DBGrid wie gehabt etwa 20-30 Sekunden. Die RAM Nutzung geht dabei auf meinem Rechner hoch bis auf 4GB (das erklärt für mich den Heap Overflow Error unter 32Bit).
Das Befüllen des StringGrid "frisst" nur ca. 80MB RAM. Auch beim Befüllen der Datenbank ist nur ein Anstieg des RAM Verbrauchs auf ca. 140MB zu sehen (also noch sehr moderat). Ab dem Befüllen des DBGrid's mit 100.000 Zeilen steigt der Speicherbedarf auf über 4GB RAM. Bei 50.000 Rows sind es 2GB. Ich vermute Windows beginnt ab ca. 3GB RAM damit, die Daten aus dem RAM auf die Platte auszulagern (daher hier dann die schlechte Performance). Aber warum frisst das DBGrid so viel mehr an RAM Resourcen im Vergleich zum StringGrid?
@wp_xyz: Debugging war in meinem Beispiel bewusst ausgeschaltet um hier die Ausführungsgeschwindigkeit nicht zu verlangsamen.

Könnt ihr bitte nochmal schauen, ob die 2 Sekunden bei 100.000 Zeilen wirklich machbar sind und wie genau? Dann wäre ich mit meinem Projekt diesbzgl. "aus dem Schneider".
Danke und Gruß
Helios

Benutzeravatar
lcb-User
Beiträge: 23
Registriert: Di 15. Jul 2014, 13:18
OS, Lazarus, FPC: Linux Mint 20.1 Cinnamon, Lazarus 2.0.12-gtk2, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: München

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von lcb-User »

Hallo Helios

Hast Du schon mal bei
SQLQuery1.PacketRecords := -1
versucht. :-)

Und
DBGird1.Options.dgThumbTracking := True
Ist auch nicht schlecht.

Ich arbeite unter Linux und hab dein Testprojekt auf meinen Rasbperry PI
aufgesetzt das schreiben auf die SD-Karte vom Raspberry hat ca 8 Min gedauert.
Aber das Select lief ganz gut. :-)

Sonnige Grüße aus München

Helios
Lazarusforum e. V.
Beiträge: 93
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.2.0 Windows 10 64Bit / Lazarus 2.0.12 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Helios »

Hallo Icb-User,

danke für Deinen Tipp. Aber leider habe ich mit der "SQLQuery1.PacketRecords := -1" ein unverändertes Verhalten.
Das Lesen in die DBGrid dauert im Schnitt 3x länger als der Insert in die frische Datenbanktabelle.
Bei 200.000 Zeilen liegt der Insert in die Tabelle bei ca. 30s (ist für mich ok) beim Einlesen in der Daten über die Datenbank in das DBGrid
sind es über 90s (ist nicht ok).
Das Laden der Daten habe ich über das StringGrid mal über CSV gemacht. Dort ist die Ladezeit so wie gewünscht bzw. schön schnell und ohne den exorbitanten RAM Bedarf (>4GB). Das Laden der Daten über eine Datenbank darf natürlich etwas länger dauern aber nicht so extrem lange wie es derzeit der Fall ist. Anbei die verbesserte Version:
  • Bitte aufpassen! Bei einer Zeilenanzahl von 200.000, braucht die Datenbank ca. 200MB, d.h. die Datenbank bläht die "netto" 20 MB Daten (wie in der CSV-Datei Größe sichtbar) auf das 10fache auf.
    DBGridFireBirdTest.V2.0.zip
    (129.74 KiB) 62-mal heruntergeladen
    Das ist aber ein Thema der Firebird Datenbank. Ich halte den Faktor 10 gefühlt für zu hoch aber habe da keine echten/guten Vergleichswerte von anderen (embedded) Datenbanken.
Leider ist die Option "DBGrid1.Options.dgThumbTracking := true;" bei der Lazarus 2.0.12 Windows 64Bit nicht vorhanden.

Eine Frage noch zum Rasbperry PI: Hast Du da schon die 64Bit Version verwendet? Funktioniert die Firebird DB auch (embedded) auf einem Rasbperry PI oder hast Du die Datenbank auf einem anderen Server installiert gehabt?

Danke und Gruß
Helios

Benutzeravatar
lcb-User
Beiträge: 23
Registriert: Di 15. Jul 2014, 13:18
OS, Lazarus, FPC: Linux Mint 20.1 Cinnamon, Lazarus 2.0.12-gtk2, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: München

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von lcb-User »

Hallo Helios
Eine Frage noch zum Rasbperry PI: Hast Du da schon die 64Bit Version verwendet?
https://www.raspberrypi.org/software/op ... -os-32-bit

Mein Raspberry PI ist im lokalen Netz eingebunden und Firebird läuft als Server 3.0
und dort habe ich die Datenbank in einen dafür vorgesehenen Ordner '/home/fbdata'
ablegen lassen. In databases.conf habe ich einen Alias 'TestDB.FDB = /home/fbdb/TestDB.FDB' angelegt und fertig!

Code: Alles auswählen

  DeleteFile('TestDB.FDB');
Das funktioniert natürlich dann nicht.
Funktioniert die Firebird DB auch (embedded) auf einem Rasbperry PI
Bei Linux funktioniert das mit 'embedded' nicht, zumindest hab ich es noch nicht hinbekommen.

Sonnige Grüße aus München :-)

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von af0815 »

Achtung RasPi ist im Normalfall 32 Bit, aktuell auch noch der RasPi 4. Da helfen 8GB Ram wenig. 64 Bit ist im entstehen und aktuell Beta.

@Helios: Ist embedded Firebird gefordert oder halt vorhanden. Ich gehe davon aus, das die DB nicht installiert werden darf, sondern nur als 'dll' embedded sein muss.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Helios
Lazarusforum e. V.
Beiträge: 93
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.2.0 Windows 10 64Bit / Lazarus 2.0.12 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Helios »

Hallo af0815,

embedded Firebird auf einem entsprechend dimensionierten Win64Bit Rechner war vorgesehen.
Ich hatte auf dem RasPi4 GNU Octave 32Bit mal zum laufen gebracht. Bei der Diskussion bzgl. 32/64 Bit dachte ich, Icb-User hat schon einen RasPi4 64Bit im Einsatz
und es lohnt sich mal die Octave 64Bit auf RasPi64Bit zu compilieren. Das ist aber ein anderes Thema und kann später mal angegangen werden:-)
Wenn ein RasPi 32Bit aber als Client die Daten von einem entsprechenden (Remote) Server schnell abfragen und anzeigen kann, dann ist das doch schon mal super (das muss ich mal unter Linux/RasPiOS aufsetzen und probieren) und sollte sich doch irgendwie auf Win64 (auch für mich:-) übertragen lassen.
Mit Win64Bit bekomme ich es einfach nicht so schnell hin wie von Dir und Soner für Win64Bit und von Icb-User RasPi32Bit beschrieben.
Das gleiche Performanceproblem habe ich auch auf einem 2. Win64Bit Rechner. Somit eigentlich kein Rechner Problem (meinerseits).
Daher nochmal die Frage zu meinem ersten Beispielcode, habt ihr da irgendwelche anderen Einstellungen genutzt? Standard Lazarus 2.0.12 Installation?
Ist der RAM Verbrauch auch so signifikant hoch ab 100.000 Zeilen (>4GB)? Könnt ihr mir bitte die 2 Sekunden bis zur Anzeige des letzten Datensatzes im DBGrid bestätigen?
Mehr Performance brauche ich dann nicht mehr...

Danke und Gruß
Helios

wp_xyz
Beiträge: 4324
Registriert: Fr 8. Apr 2011, 09:01

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von wp_xyz »

Mit dem Programm v2 habe ich folgende Ergebnisse (Zeitangaben lt deinem Programm; Win10, Laz-trunk/FPC3.2.0/64 bit):

- 50.000 Zeilen ins StringGrid schreiben: 3s
- In die DB schreiben: 10s
- DBGrid füllen: 2s, Speicherbedarf ca 2 GB
- Scrollen im DBGrid: instantan, keine Verzögerung

- 100.000 Zeilen ins StringGrid schreiben: 6 s
- in die DB schreiben: 20s
- DBGrid füllen: 7s, Speicherbedarf 4 Gb
- Scrollen im DBGrid: keine Verzögerung

- 200.000 Zeilen ins StringGrid schreiben: 12 s
- in die DB schreiben: 40 s
- DBGrid füllen: 22 s, Speicherbedarf: 8GB
- Scrollen im DBGrid: keine Verzögerung

Überschlagsrechnung wegen Speicherbedarf: Speicherbedarf für Felder 240+240+5+1000+1000+8000+1000+240 = ca 12.000 Byte pro Record. Bei 100.000 Zeilen sind das etwa 1 GB - wo die restlichen 3GB hingehen, weiß ich nicht...

Und so bekommst du das Thumbtracking zum Laufen:

Code: Alles auswählen

Grid.Options := Grid.Options + [goThumbTracking];

Soner
Beiträge: 513
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Soner »

Es waren 50.000 Datensätze. Du bringst in deinem Test und allgemein einiges durcheinander.
1.
Dein "Tabelle und Einträge erzeugen"-Knopf erzeugt Tabelle in DB-Server und danach holt es Datensätze.
Das kannst du nicht machen um Zeit zu messen. Du musst Tabellenerzeugung und Datenholen("Select * from xyz) getrennt betrachen. Du hasst doch am Anfang angegeben, dass die Daten von Oracle-DB-Server geliefert werden.
Deshalb musst du nur Auswahlfunktion betrachten, deshalb habe ich eine zusätzliche Funktion geschrieben um nur die Zeit für 'SELECT * FROM messwerte' zur betrachten.
2.
DBGrid verbraucht kaum Speicher, weil es im Vergleich zu StringGrid keine Daten speichert. Was Speicher verbraucht ist die Komponente TSQLQuery, weil diese Komponente die ganzen Daten puffert. DBGrid speichert nicht mal ein Feldwert, bei jedem Paint-Ergeignis holt die DGBrid die Daten von SQLQuery. DBGrid ist ziemlich schnell, weil es nur die sichtbaren Zeilen durchläuft. Auch wenn es die letzten 10 anzeigt, fängt es nicht von 0 an, sondern die letzte Zeile minus die sichtbare Zeilenanzahl.
3.
Die langsamste Komponente in deinem Programm ist das Netzwerk. Ich nehme an, dass der Oracle-Server ist irgendwo im Netzwerk, dann dauert natürlich mehrere GB-Daten übers Netzwerk zu holen eine Weile.
Hast du schonmal im Netzwerk 3-5 GB große Datei von einem Computer zum anderen kopiert und dabei die vergangene Zeit beochtet? Das dauert meistens 5-10 Minuten.
Bei meinem Beispiel lag sowohl FB-Server als auch Beispielprogramm im gleichen Computer.
4.
Wenn der DB-Server irgendwo im Netzwerk liegt, dann darf man nie alle auf einmal holen, falls die Daten, wie in deinem Fall, sehr groß sind.

Ich teste mal gleich große Datenmengen und poste Ergebnis hier.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von af0815 »

Testdatei aus dem Beispiel ohne Änderung:
- 200.000 Zeilen ins StringGrid schreiben: 25 s
- in die DB schreiben: 32s
- DBGrid füllen: 64 s, Speicherbedarf: 8.8GB
- Scrollen im DBGrid: keine Verzögerung
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Helios
Lazarusforum e. V.
Beiträge: 93
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.2.0 Windows 10 64Bit / Lazarus 2.0.12 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Helios »

Hallo wp_xyz,

puh, nee leider schaffe ich diese Zahlen nicht. Beim Einlesen in das DBGrid verbrauche ich immer erkennbar mehr Zeit als beim Insert in die Datenbank, und das verstehe ich nicht.

- 100.000 Zeilen ins StringGrid schreiben: 13 s
- in die DB schreiben: 16 s
- DBGrid füllen: 19 s.

Unter Linux (Debian Bullseye 64Bit, Lazarus 2.0.10, Firebid 3.0 über localhost als Server auf der gleichen Maschine):

- 100.000 Zeilen ins StringGrid schreiben: 14 s
- in die DB schreiben: 175 s (kein Schreibfehler!!! Da muss ich nochmal in den Firebird Server Einstellungen "herumwerkeln".)
- DBGrid füllen: 18 s, also mit Win64 vergleichbar.

Einen Virenscanner unter Windows als Ursache für die langen Zeiten DBGrid Einlesezeiten würde ich jetzt ausschliessen. Lazarus 2.0.12 ist es nicht, da 2.0.10 unter Linux sich ähnlich verhält. Ich schaue mal, wenn ich das StringGrid "händisch" über einen SQL Select (also ohne DBGrid) fülle, ob ich damit schneller bin.
Danke aber euch allen für die Unterstützung und Gruß
Helios

Soner
Beiträge: 513
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Soner »

wp_xyz hat geschrieben:
Mo 26. Apr 2021, 14:48
Überschlagsrechnung wegen Speicherbedarf: Speicherbedarf für Felder 240+240+5+1000+1000+8000+1000+240 = ca 12.000 Byte pro Record. Bei 100.000 Zeilen sind das etwa 1 GB - wo die restlichen 3GB hingehen, weiß ich nicht...
Er füllt ja erstmal StringGrid, dann von StringGrid zum DB-Server, anschließend vom DB-Server zurück zum SQLQuery1. Er hat die Daten dreifach.

wp_xyz
Beiträge: 4324
Registriert: Fr 8. Apr 2011, 09:01

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von wp_xyz »

Aber das StringGrid würde ich vernachlässigen - es enthält ja nur die Strings in der "echten" Länge, nicht die überdimensionierten 1000er und 8000er Felder.

Soner
Beiträge: 513
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Soner »

100.000 Datensätze dauern bei mir 9 Sec.
Ich habe eine Select-Funktion hinzugefügt, Programm neu gestartet und nur Select-Funktion ausgeführt trotzdem dauert die Auswahl 9 sekunden und Speicherverbrauch wieder 4.2 GB.

Code: Alles auswählen

procedure TForm1.BtnSelectClick(Sender: TObject);
var
  FromTime,
  ToTime:      TDateTime;
  DiffSeconds: integer;
begin
  IBConnection1.DatabaseName := 'TestDB.FDB';
  IBConnection1.UserName     := 'SYSDBA';
  IBConnection1.Password     := 'masterkey';
  IBConnection1.Charset := 'UTF8'; //Send and receive string data in UTF8 encoding
  IBConnection1.Dialect := 3; //Nobody uses 1 or 2 anymore.
  IBConnection1.Params.Add('PAGE_SIZE=8192');
  IBConnection1.Transaction := SQLTransaction1;
  IBConnection1.Open;

  FromTime := Now;

  //read table data into DBGrid
  try
    SQLQuery1.SQL.Text:= 'SELECT * FROM messwerte';
    SQLTransaction1.Active:= True;
    //SQLQuery1.PacketRecords := -1;
    //DBGrid1.Options.dgThumbTracking := true;
    DBGrid1.BeginUpdate;
    SQLQuery1.Open;
    SQLQuery1.Last;
    SQLQuery1.First;
    DBGrid1.EndUpdate;
    //DBGrid1.DataSource := DataSource1;
    //SQLQuery1.EnableControls;
  except
    on E : Exception do
    begin
      ShowMessage('Fehler beim Einlesen der Daten in das DBGrid!');
      exit
    end;
  end;
  ToTime := Now;

  DiffSeconds := SecondsBetween(ToTime,FromTime);

  Label2.visible := false;
  Label2.caption := 'Für Select Zeit: ' + IntToStr(DiffSeconds) + ' Sekunden.';
  Label2.Font.color := clGreen;
  Label2.visible := true;

  Screen.Cursor := crDefault;
  //SQLQuery1.EnableControls;
  DBGrid1.AutoAdjustColumns;
end;
Ich glaube den enormen Speicherverbrauch verursacht Firebird-Server, weil es für jedes Zeichen, auch für utf8, 4 Bytes reserviert. Also wenn man 80 Zeichen lange UTF8-Char-Feld hat, dann macht FB daraus 80*4=320 Bytes.

Soner
Beiträge: 513
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von Soner »

Soner hat geschrieben:
Mo 26. Apr 2021, 18:05
Ich glaube den enormen Speicherverbrauch verursacht Firebird-Server, weil es für jedes Zeichen, auch für utf8, 4 Bytes reserviert. Also wenn man 80 Zeichen lange UTF8-Char-Feld hat, dann macht FB daraus 80*4=320 Bytes.
Aus diesem Grund habe ich bei meinem Lazarus-Version für TColumn neues Feld "Fieldlength" eingeführt, damit die Länge für String-Felder richtig übernommen wird.

Benutzeravatar
lcb-User
Beiträge: 23
Registriert: Di 15. Jul 2014, 13:18
OS, Lazarus, FPC: Linux Mint 20.1 Cinnamon, Lazarus 2.0.12-gtk2, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: München

Re: DBGrid bei Firebird Datenbank Abfragen bei Zeilenanzahl > 100.000 sehr langsam

Beitrag von lcb-User »

Hallo zusammen,

Ich hab mich den ganzen Tag mit DBGridFireBirdTest.V2.0 beschäftigt.
Ich habs mit CodeTyphon an meine Gegebenheiten angepasst.

Habe auch das System bis zum Anschlag belastet. 400000 Datensätze haben zum Stillstand und dann zum Absturz des Programms geführt.

Aber der Hinweis von Soner
Ich glaube den enormen Speicherverbrauch verursacht Firebird-Server, weil es für jedes Zeichen, auch für utf8, 4 Bytes reserviert. Also wenn man 80 Zeichen lange UTF8-Char-Feld hat, dann macht FB daraus 80*4=320 Bytes
hat mich dazu verleitet

Code: Alles auswählen

 IBConnection1.Charset := ''; //'UTF8'; //Send and receive string data in UTF8 encoding
Charset auf Null zustellen.

Ein verblüffender Effekt
Wenn keine Sonderzeichen und Umlaute gebraucht werden?!
Tabellenabfragen laufen wie geschmiert. "DBGrid gefüllt mit 100000 Zeilen. Benötigte Zeit dafür: 1 Sekunde.

Sonnige Grüße aus München

Antworten