Firebird unter Debian 10 (Buster) deutlich langsamer als unter Debian 9 (Stretch)

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

Moderator: thorben.braun

Antworten
dirk.jansen
Beiträge: 5
Registriert: Di 30. Mär 2021, 13:37

Wir haben eine Software basierend auf einer Firebird Datenbank. Diese läuft schon seit Jahren auf Debian Servern. Nach dem Update der Server von Debian 9 (Strech, Firebird 3.0.2) auf Debian 10 (Buster, Firebird 3.0.5) ist das Programm langsamer geworden. Der Effekt ist dabei unabhängig von der Hardwareausstattung der Server oder davon, ob es virtualisiert ist oder nicht.

Um, das Problem zu untersuchen haben wir die 3 gleich konfigurierte virtuelle Server mit Debain 9, 10 und 11 installiert, dieselbe Kundendatenbank darauf aus einem Backup zurück gelesen und dann die Performance gemessen.

Dabei sind wir auf ein – zugegeben extremes – Beispiel gestoßen:
Die Abfrage

Code: Alles auswählen

SELECT L.AKT_ID, COUNT(L.LGS_ID) AS AktCnt
  FROM AKTION L
    JOIN SATZ S ON (L.LGS_ID = S.LGS_ID) AND (S.AUSGANG IS NULL) AND (S.VERLOREN_FLG = 'N')
  WHERE (L.ERLEDIGT IS NULL)
    AND (L.STORNO_FLG = 'N')
    AND (NOT L.AKT_ID IN (5, 8, 3, 58, 59, 60))
  GROUP BY l.Akt_ID;
  
Läuft nach einem Reboot auf dem Debian 9 Server in ca. 45 Sekunden durch, wenn man Sie erneut ausführt benötigt sie noch ca. 1,6 Sekunden.
Die gleiche Abfrage benötigt unter Debian 10 und 11 ca. 14 Minuten(!). Sie wird auch nicht schneller, wenn man sie erneut ausführt.

Der Queryplan ist auf allen Versionen gleich:

Code: Alles auswählen

PLAN SORT (JOIN (S INDEX (IDX_SATAUSGANG), L INDEX (RDB$FOREIGN34)))
Wenn man die Abfrage umformuliert:

Code: Alles auswählen

SELECT L.AKT_ID, COUNT(L.LGS_ID) AS AktCnt
  FROM AKTION L
  WHERE (L.ERLEDIGT IS NULL)
    AND (L.STORNO_FLG = 'N')
    AND (L.AKT_ID NOT IN(5, 8, 3, 58, 59, 60))
    AND EXISTS (SELECT LGS_ID 
                  FROM SATZ S
                  WHERE (S.LGS_ID = L.LGS_ID)
                    AND (S.AUSGANG IS NULL)
                    AND (S.VERLOREN_FLG = 'N'))
  GROUP BY l.Akt_ID;
Läuft sie auf allen 3 Varianten beim ersten Mal 30 Sekunden und beim zweiten Aufruf ca. 10 Sekunden Auf dem Debian 11 (Firebird 3.0.7) Server ca 7. Sekunden.

Das Ergebnis besteht aus 11 Zeilen mit Insgesamt 29.499 betroffenen Datenätzen. Die Tabelle SATZ enthält 354.239 Zeilen, die Tabelle AKTION 6.613.330 Zeilen.

Kennt jemand diesen Effekt?

Vielen Dank im Voraus
Dirk
Benutzeravatar
martin.koeditz
Beiträge: 283
Registriert: Sa 31. Mär 2018, 14:35

Hi Dirk,

bitte mache, wenn möglich, ein Update auf Firebird 3.0.7. Dort gab es Verbesserungen in der Performance zu Vorgängerversionen. Sollte das nichts bringen, sollten wir uns mal deine Konfigurationen ansehen.

Wurde das Dateisystem in den neueren Debian-Varianten geändert? Wir hatten mal enorme Schwierigkeiten mit Btrfs.

Gruß
Martin
Martin Köditz
it & synergy GmbH
dirk.jansen
Beiträge: 5
Registriert: Di 30. Mär 2021, 13:37

Hallo Martin.

Danke erst mal für Deine Antwort.

Wir haben Debian 11 (Bullseye) ebenfalls getestet. Darin ist Firebird 3.0.7 enthalten. Die Zeiten entsprechend denen aus Debian 10 (Firebird 3.0.5).

Alle drei Server wurden neu mit Standard-Einstellungen installiert. In der firebird.conf habe ich bei keiner der Varianten etwas eingetragen. Ab Debian 10 ist

Code: Alles auswählen

UdfAccess = None
eingetragen. Testweise habe ich das auch bei dem Debian 9 Server gesetzt, keine Änderung. Ansonsten ist die firebird.conf leer (bis auf die üblichen Kommentare).

Dateisystem für alle drei Installationen ist ext4. Die Mountoptionen sind bis auf die Angabe data=ordered gleich. Diese wird nur bei Debian 9 angezeigt. Allerdings ist data=ordered für Debian 10 und 11 die Standardeinstellung für Ext4 und man kann es auch nicht manuell eintragen.

Dirk
dirk.jansen
Beiträge: 5
Registriert: Di 30. Mär 2021, 13:37

Ich habe es gefunden!

Im Gegensatz zu meinem ersten Post war der Queryplan doch nicht gleich. Ich hab das wohl übersehen:
Auf Debian 9, Firebird 3.0.2:

Code: Alles auswählen

PLAN SORT (JOIN (S INDEX (IDX_SATZAUSGANG), L INDEX (RDB$FOREIGN265)))
Und auf Debian 10/11, Firebitd 3.0.5/3.0.7:

Code: Alles auswählen

PLAN SORT (JOIN (S INDEX (IDX_SATZAUSGANG), L INDEX (RDB$FOREIGN265, IDX_AKTIONERLEDIGT)))
Da führt dann unter unter Debian 9, Firebird 3.0.2 zur der folgenden Statistik:
Current memory = 542500944
Delta memory = 877912
Max memory = 546698184
Elapsed time= 46.915 sec
Cpu = 0.000 sec
Buffers = 61440
Reads = 26940
Writes = 0
Fetches = 954988
Unter Debian 10/11, Firebird 3.0.5/3.0.7 ergibt sich die folgende Statistik:
Current memory = 542172160
Delta memory = 874944
Max memory = 546369440
Elapsed time= 860.048 sec
Cpu = 0.000 sec
Buffers = 61440
Reads = 13767
Writes = 0
Fetches = 16356384
Der zusätzlich eingebundene Index führt zu mehr als 16 mal so vielen Fetchtes und damit auch zur ca. 16 fachen Laufzeit.

Wenn man unter Debian 10/11, Firebird 3.0.5/3.0.7 den (unnötigen) Index IDX_AKTIONERLEDIGT
abschaltet

Code: Alles auswählen

ALTER INDEX IDX_AKTIONERLEDIGT INACTIVE;
ergibt sich der gleiche Queryplan wie auch unter Debian 9, Firebird 3.0.2:

Code: Alles auswählen

PLAN SORT (JOIN (S INDEX (IDX_SATZAUSGANG), L INDEX (RDB$FOREIGN265)))
mit der folgenden Statistik:
Current memory = 542131760
Delta memory = 833936
Max memory = 546329040
Elapsed time= 1.233 sec
Cpu = 0.010 sec
Buffers = 61440
Reads = 26945
Writes = 0
Fetches = 630860
Uns das ist dann sogar schneller.

fbstat liefert für den Index IDX_AKTIONERLEDIGT:
Index IDX_AKTIONERLEDIGT (7)
Root page: 569824, depth: 3, leaf buckets: 4460, nodes: 6613330
Average node length: 5.43, total dup: 5379550, max dup: 1172106
Average key length: 2.44, compression ratio: 2.68
Average prefix length: 6.09, average data length: 0.46
Clustering factor: 1058922, ratio: 0.16
Fill distribution:
0 - 19% = 1
20 - 39% = 0
40 - 59% = 0
60 - 79% = 0
80 - 99% = 4459
Also 5.3 Mio Duplikate wobei der Max Dup bei 1.2 Mio liegt. Der Index hat eine geringe Selektivität. Gemäß Dokumentation wird diese Verhältnis herangezogen um zu ermitteln ob der Index in Abfragen verwandt werden soll. Ich vermute hier hat sich ein interner Grenzwert im Firebird geändert,weshalb er den Index jetzt für die Abfrage heranzieht.

Fazit:
  • Ich habe einen für diese Abfrage unnötigen Index in der Datenbank.
  • Der Optimierer bei Firebird 3.0.2 erkennt, das der Index nicht notwendig ist und verwendet ihn nicht. Oder er erkennt nicht, das er den Index verwenden könnte
  • Der Optimierer unter Firebird 3.0.5, verwendet den unnötigen Index und macht die Abfrage damit langsamer
  • Das Betriebssystem ist unschuldig
Ich hoffe diese Informationen helfen irgendjemanden mal weiter

Dirk
Benutzeravatar
martin.koeditz
Beiträge: 283
Registriert: Sa 31. Mär 2018, 14:35

Hallo Dirk,

super, dass du den Fehler bereits gefunden hast. Und danke, dass du uns daran teilhaben lässt. Das hilft bestimmt jemandem weiter.

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

Werden die Index-Statistiken denn regelmäßig aktualisiert?
Dies passiert leider nicht automatisch.
Wie siehts aus, wenn du mal "set statistics all" ausführst und die Tests wiederholst?
Ich setze aktuell 3.0.5 (auf Windows) ein, aktualisiere allerdings regelmäßig die Index Statistik und habe bisher noch keine Performance-Nachteile erlebt.
Zusätzlich führe ich 1x wöchentlich (sonntags) einen save/restore durch um die Datenbank ebenso zu restrukturieren (entspricht wie im Filesystem einem Defrag).
Bei 70GB dauert dies ca. 2 Stunden.
dirk.jansen
Beiträge: 5
Registriert: Di 30. Mär 2021, 13:37

Wir machen kein kegelmäßiges Backup/Restore und wir aktualisieren auch keine Index Statistiken. In den vergangen 15 Jahren (so lange läuft die Anwendung) war das zumindest bei unserem Anwendungsfall nicht notwendig. Wir machen ab eigentlich nur ein Backup/Restore, wenn die Kunden einen neuen Server bekommen, oder wenn wir die Firebird Version wechseln.

Ist das tatsächlich notwendig? Ich habe Firebird in der Vergangenheit immer als ein Datenbanksystem wahrgenommen, bei dem sehr wenig Pflege der Datenbanken notwendig ist.

""set statistics all" funktioniert nicht unter Debian 10/Firebird 3.0.5. Ich habe die betroffenen Indices manuell aktualisiert, aber es ändern sich weder die Zahlen aus der Statistik noch ändert sich das Laufzeitverhalten.

Da ich die Datenbank für den Test aus einem Backup wiederhergestellt habe, war das aber auch nicht zu erwarten. Im Rahmen der Wiederherstellung werden auch die Indices neu aufgebaut. Zumindest schreibt gbak das in die Konsole.
bfuerchau
Beiträge: 276
Registriert: Mo 7. Mai 2018, 18:09

Nun ja, was ist schon normal ;) .
Wir verwenden die DB als Datawarehouse mit extrem vielen Massendeletes/-inserts (> 100.000 Zeilen), create/drop tables (temporäre dynamische Tabellen für indizierbare Zwischenergebnisse, da global temporäry tables nicht indizierbar sind, create index in Abhängigkeit der Abfrage). Da stimmt häufiger mal die Selektivität nicht.
Bei der klassischen Verwendung werden die Probleme wohl eher seltener bis gar nicht auftreten.
Alleine durch dieses Verfahren bleiben schon mal DB-Blöcke (16KB) verwaist in der DB. Auch der Sweeper schafft es dann nicht immer, wieder aufzuräumen. Im Log stehen da schon mal die üblichen Hinweise auf falsche Blockverweise.
Da ist dann ein Save/Restore doch wieder erforderlich. Da dieser dann auch schon mal scheitert, ist ein sog. Replicate (von mir) erforderlich, der dann Tabelle für Tabelle, Zeile für Zeile in eine neue DB kopiert. Das dauert dann schon mal 12-16 Stunden.
Aber beim Datenteil einer DB haben wir noch nie Fehler gehabt.
Dies machen wir seit FB 2.0 und hat sich bzgl. der Fehlerquote und Sicherheit mit 3.0.5 noch nicht geändert.

Durch extrem viele Transaktionen (auch beim Select) musste ab und an ein Save/Restore durchgeführt werden um denTransaktionszähler wieder zurück zu setzen. Seit 3.0 ist der nun BIGINT und hält daher länger.

Ein Hauptproblem ist die Virtualisierung. Wir haben massive Probleme wenn eine VM gesichert wird und der FB-Dienst noch läuft. Da die FB immer noch keinen VSS-Writer hat, ist eine VM-Sicherung nur bei abgeschalteter VM oder FB-Dienst möglich. Wenn man sich daran nicht hält wird die DB regelmäßig korrupt, da die externe Sicherung das Verändern von Plattenbereichen sperrt und der FB-Dienst das nicht merkt.
dirk.jansen
Beiträge: 5
Registriert: Di 30. Mär 2021, 13:37

Wir erstellen eigentlich immer eine Sicherung mit GBAK auf eine lokale Platte und sicheren danach die VM weg. Damit haben wir noch nie Probleme gehabt.

Allerdings verwenden wir seit seit ca. 10 Jahren fast ausschließlich Debian Server für Firebird Datenbanken. Seit dem ist der Supportaufwand deutlich gesunken. Das liegt allerdings mehr an Debian/Windows als am Firebird. Der hat eigentlich (für unsere Anwendungen) nie Probleme gemacht.

Wir verwenden Firebird seit der Version 1.5 (vorher hatten wir Interbase 5 und 6) und ich kann mich nicht erinnern, das wir bei mehr als 50 Servern jemals eine korrupte Firebird Datenbank hatten.
Antworten