1-TB-Firebird-Datenbank: vorläufiger Bericht
Dmitry Kuzmenko, letzte Aktualisierung 31.03.2014
Übersetzungen dieses Dokuments: Portugiesisch Russisch Chinesisch
Lesen Sie unseren Artikel über eine noch größere (1,7 Terabyte) Datenbank: Weitere Details zur 1,7-Terabyte-Datenbank.
Warum eine Terabyte-Firebird-Datenbank erstellen?
Viele Unternehmen arbeiten mit großen Firebird-Datenbanken und verlassen sich auf sie, um wichtige Geschäftsabläufe zu unterstützen. Einige Firebird-Datenbanken sind bereits hunderte Gigabyte groß und wachsen weiter (siehe Abschnitt „Wer ist groß?“), und es ist leicht vorherzusagen, wann sie 2, 3 oder 5 Mal größer werden. Daher sind Datenbankadministratoren und Anbieter daran interessiert, das Verhalten von Firebird mit großen Datenbanken zu untersuchen und Empfehlungen für deren Verwaltung zu erhalten.
Ein weiterer wichtiger Grund, den wir beim Erstellen der 1-Tb-Firebird-Datenbank im Sinn hatten, war die endgültige Beseitigung der vorherrschenden Wahrnehmung von Firebird als Datenbank-Engine für „kleine Datenbanken“. Dieser Mythos scheint nun tot zu sein, aber einige Analysten und Journalisten holen ihn regelmäßig aus dem Grab, und wir hoffen, diese lächerliche Wahrnehmung endlich zu beenden.
| ## Hardware |
Firebird ist bekannt für seine unglaubliche Skalierbarkeit, und diese Untersuchung hat dies erneut bestätigt. Der ursprüngliche Zweck dieses Experiments war lediglich die Erstellung einer Firebird-Datenbank mit 1 Tb Größe, daher verwendeten wir einen gewöhnlichen Desktop-Computer:
Tabelle 1: Hardware
| Komponente | Parameter |
| CPU | AMDAthlon 64 x2 5200 |
| RAM | 4GB |
| Motherboard | MSI K9N Platinum |
| HDD1 (Betriebssystem und Temp) | ST3160815AS, 160GB, SATA II |
| HDD2 (Hilfslaufwerk) | HDT721064SLA360, 640GB,SATAII |
| HDD2 (Hilfslaufwerk) | HDS728080PLA380, 80GB, SATA I |
| HDD3 (Datenbank) | ST31500341AS, 1.5TB, SATA II (Firmware CC1H) |
Im Wesentlichen haben wir die 1,5-Tb-Festplatte in einen unserer Büro-Desktops eingebaut, ohne weitere Änderungen. Diese Festplatte wurde mit einer Clustergröße von 16 Kb formatiert (dieselbe wie die Seitengröße der Datenbank, wie Sie unten sehen können).
Software
Da es sich um einen Desktop-Computer handelt, ist das Betriebssystem Windows XP Professional SP3, 32 Bit. Um den Test tatsächlich durchzuführen, verwendeten wir den Loader aus dem TPC-basierten Toolkit (laden Sie es von http://ibdeveloper.com/tests/tpc-c/ herunter, sowohl Binärdateien als auch Quellcode sind verfügbar).
Wir möchten betonen, dass der Loader Daten so einfügt, wie sie in einem realen Szenario eingefügt würden: Datensätze werden eingefügt und in der Datenbank (und in physischen Festplattenbereichen) in mehreren Master-Detail-Subdetail-Tabellen platziert, nicht Tabelle für Tabelle.
Tabelle 2: Software
| Software | Version |
| Betriebssystem | Windows XP Professional SP3, 32bit |
| Firebird | 2.1.3 SuperServer (Snapshot) |
| Loader | Benutzerdefinierter Loader aus dem TPC-basierten Test |
Plan
Wir hatten einen sehr geradlinigen Plan für dieses Experiment:
- Datenbank erstellen und mit 1 Tb Daten laden, ohne Indizes
- Primärschlüssel und entsprechende Indizes erstellen (sodass die Datenbankgröße tatsächlich mehr als 1 Tb beträgt)
- Datenbankstatistiken sammeln
- Mehrere SQL-Abfragen ausführen und die Datenbankleistung bewerten
Datenbank- und Firebird-Server-Konfiguration
Die Datenbank hat eine Seitengröße von 16384 Bytes, dieselbe wie die HDD-Clustergröße, um den Festplattendurchsatz zu maximieren (1 Seite in einem E/A-Zyklus lesen/schreiben).
In der Firebird-Konfiguration haben wir ein zusätzliches Verzeichnis für Temp-Speicherplatz konfiguriert und es auf die Festplatte mit 640 Gb verwiesen (wo ~300 Gb frei waren).
Ladeschritt
Die Daten wurden in mehreren Schritten in diese Datenbank geladen. Der Computer wurde während der Ladevorgänge als gewöhnlicher Desktop verwendet (wir haben MS Office, Firefox, IBAnalyst usw. – etwa 8–12 Programme liefen gleichzeitig). Wenn wir die Hardware ausschließlich für diese Aufgabe vorgesehen hätten, wäre es wahrscheinlich schneller gewesen, daher betrachten Sie diese Werte bitte nur als ein Low-End-Beispiel; sie sind definitiv nicht die Spitzenergebnisse.
Tabelle 3: Ladevorgänge
| |
| Beschreibung | Wert |
| Ladezeit | ~70 Stunden |
| Insgesamt eingefügte Datensätze | 6,2 Milliarden |
| Durchschnittliche Einfügegeschwindigkeit | 24500 Datensätze/Sekunde |
| Durchschnittliche Datensatzgröße | 146 Bytes (min 13 Bytes, max - 600 Bytes) |
| Transaktionen | 646489 |
Wir verbrachten ~4 Tage mit dem Laden, und danach hatten wir eine Firebird-Datenbank mit genau 1 Tb Größe (d. h. 1 099 900 125 184 Bytes).
Unten sehen Sie das Datenbankwachstum und die Transaktionsdynamik im FBDataGuard Viewer:

Indizes
Wir erstellten die Indizes nacheinander und erfassten ihre Erstellungszeiten und die entsprechende Größe der für die Sortierung verwendeten Temp-Datei.
Der größte Index wurde für die Tabelle ORDER_LINE erstellt. Sein Primärschlüssel enthält vier Felder (Smallint, Smallint, Integer und Smallint). Die Temp-Datei für diesen Sortierindex war 182 Gb groß, und die endgültige Indexgröße in der Datenbank beträgt 29,3 Gb.
Es ist interessant zu sehen, dass selbst der Index für eine Tabelle mit 3,8 Milliarden Datensätzen eine Tiefe = 3 hat, weil die Seitengröße 16384 Bytes betrug, sodass beim Suchen von Daten über den Primärschlüssel für diese Tabelle kein Overhead entsteht.
Statistiken
Danach haben wir die Datenbankstatistiken gesammelt. Es dauerte 7 Stunden 32 Minuten 45 Sekunden.
Wir haben die wichtigsten statistischen Informationen in einer Tabelle zusammengefasst und einige Abfragen und Zeitmessungen aufgenommen:
Tabelle 4: Konsolidierte Statistiken für die 1-Tb-Datenbank
| Tabellenname | Datensatzanzahl | Größe, gb | Ausführungszeit von select count(*) | Index-Erstellungszeit | Tmp-Dateigröße, Gb | Indexgröße, Gb |
| WAREHOUSE | 1240 | 0.002 | 0s | 0 | 0 | 0.0 |
| ITEM | 100000 | 0.012 | 0.7s | - | - | 0.0 |
| DISTRICT | 124000 | 0.017 | 0.7s | 6 | - | 0.0 |
| NEW_ORDER | 111600000 | 32 | 20m 00s | 23m 00s | 4.56 | 0.8 |
| CUSTOMER | 372000000 | 224 | - | 41m 00s | - | 2.6 |
| customer_last | 1h 52m 32s | 12.4 | 2.3 | |||
| fk_cust_ware | 2h 10m 51s | - | 2.3 | |||
| HISTORY | 372000000 | 32 | - | - | - | - |
| ORDERS | 372000000 | 25 | 32m 00s | 45m 41s | 15.2 | 2.5 |
| STOCK | 1240000000 | 404 | - | 3h 34m 44s | 41.5 | 9.2 |
| ORDER_LINE | 3720051796 | 359 | - | 12h 6m 18s | 182.0 | 29.3 |
Die Datenbankstatistiken können hier heruntergeladen werden.
Sie können den kostenlosen FBDataGuard Community Edition Viewer verwenden, um Textdaten zu interpretieren und nicht nur Datenbankleistungsmetriken, sondern auch CPU- und Speicherverbrauch zu sehen.
Abfragen
Zunächst haben wir select count(*)-Abfragen auf mehreren Tabellen ausgeführt (siehe 4. Spalte in Tabelle 4 oben). Wie Sie wissen, ist select count(*) für die gesamte Tabelle aufgrund der Multi-Version-Natur von Firebird eine teure Operation für den Server, da sie den Besuch jeder Seite erfordert, und erfahrene Firebird-Entwickler verwenden select count(*) nicht, aber wir haben es verwendet, um das Gesamtleistungsverhältnis von Datenbank und Hardware zu demonstrieren.
Nach den select count-Abfragen haben wir Abfragen aus einem realen Szenario ausgeführt, und um ehrlich zu sein, waren wir von den so guten Ergebnissen erstaunt. Überzeugen Sie sich selbst:
| Abfrage | Statistiken | Beschreibung |
| select w_id, w_name, c_id, c_last from WAREHOUSE, customer where c_w_id = w_id |
PLAN JOIN (WAREHOUSE NATURAL, CUSTOMER INDEX (FK_CUST_WARE)) ------ Performance info —— Prepare time = 15ms Execute time = 79ms Avg fetch time = 6.08 ms Current memory = 272 264 476 Max memory = 272 514 048 Memory buffers = 16 384 Reads from disk to cache = 82 Writes from cache to disk = 0 Fetches from cache = 3 648 |
Einfacher Join von Tabellen mit 12400 und 372000000 Datensätzen, keine WHERE-Bedingungen. „Avg fetch time = 6.08 ms“ gilt für das Abrufen der ersten Zeile. |
| select w_id, w_name, c_id, c_last from WAREHOUSE, customer where c_w_id = w_id and c_w_id = 10000 |
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE)) ------ Performance info —— Prepare time = 16ms Execute time = 78ms Avg fetch time = 6.00 ms Current memory = 272 266 148 Max memory = 272 514 048 Memory buffers = 16 384 Reads from disk to cache = 88 Writes from cache to disk = 0 Fetches from cache = 3 656 |
Join derselben Tabellen mit einer Bedingung, die die Auswahl aktueller Datensätze erzwingt. „Avg fetch time = 6.00 ms“ gilt für das Abrufen der ersten Zeile. |
| select count(*) from WAREHOUSE, customer where c_w_id = w_id and c_w_id = 10000 Result = 30000 |
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE)) ------ Performance info —— Prepare time = 0ms Execute time = 453ms Avg fetch time = 453.00 ms Current memory = 272 263 844 Max memory = 272 514 048 Memory buffers = 16 384 Reads from disk to cache = 1 048 Writes from cache to disk = 0 Fetches from cache = 60 024 |
Datensätze für die vorherige Abfrage zählen |
| SELECT * FROM ORDER_LINE WHERE OL_W_ID = 500 |
Plan PLAN (ORDER_LINE INDEX (ORDER_LINE_PK)) ------ Performance info —— Prepare time = 0ms Execute time = 94ms Avg fetch time = 7.23 ms Current memory = 136 445 536 Max memory = 136 592 176 Memory buffers = 8 192 Reads from disk to cache = 150 Writes from cache to disk = 0 Fetches from cache = 2 402 |
Abfrage auf die größte Tabelle (3,8 Mrd. Datensätze). „Avg fetch time = 7.23 ms“ gilt für das Abrufen der ersten Zeile. |
<br>Plan<br><br>PLAN (ORDER_LINE INDEX (ORDER_LINE_PK))<br><br> <br><br>------ Performance info ------<br><br>Prepare time = 0ms<br><br>Execute time = 3s 438ms<br><br>Avg fetch time = 0.01 ms<br><br>Current memory = 136 445 496<br><br>Max memory = 136 592 176<br><br>Memory buffers = 8 192<br><br>Reads from disk to cache = 1 840<br><br>Writes from cache to disk = 0<br><br>Fetches from cache = 598 636<br> |
| SELECT * FROM ORDER_LINE
WHERE OL_W_ID = 500 | Dieselbe Abfrage auf der größten Tabelle (3,8 Mrd. Datensätze), aber diesmal haben wir alle Datensätze abgerufen (299245 Datensätze abgerufen). |
| | |
| select w_id, w_name, c_id, c_last
from WAREHOUSE, customer
where c_w_id = w_id and (c_w_id > 8000) and (c_w_id < 10000) | Plan
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE))
------ Performance info ——
Prepare time = 0ms
Execute time = 125ms
Avg fetch time = 9.62 ms
Current memory = 272 270 824
Max memory = 272 514 048
Memory buffers = 16 384
Reads from disk to cache = 91
Writes from cache to disk = 0
Fetches from cache = 3 659 | Join von Tabellen mit 1240 Datensätzen und 372 Mio. Datensätzen. |
| select count(*)
from WAREHOUSE, customer
where c_w_id = w_id and (c_w_id > 8000) and (c_w_id < 10000)
Result = 59 970 000 | Plan
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE))
------ Performance info ——
Prepare time = 0ms
Execute time = 13m 4s 718ms
Avg fetch time = 784 718.00 ms
Current memory = 272 268 532
Max memory = 272 514 048
Memory buffers = 16 384
Reads from disk to cache = 2 332 583
Writes from cache to disk = 0
Fetches from cache = 119 977 902 | Datensätze für die vorherige Abfrage zählen |
Zusammenfassung
In diesem Experiment zeigt Firebird die folgenden Ergebnisse
-
Zweifelsfreie Fähigkeit, große Datenbanken zu bewältigen. Wir sind ziemlich sicher, dass es möglich ist, eine 32-Tb-Datenbank auf geeigneter Hardware zu erstellen und zu nutzen, und Firebird wird dieselbe hohe Performance zeigen wie bei kleineren Datenbanken (d. h. 1 Tb und darunter).
-
Gute Skalierbarkeit und erstaunlich geringer Ressourcenbedarf. Die 1-Tb-Datenbank wurde auf einem gewöhnlichen Desktop-Computer erstellt und – was noch wichtiger ist – sie kann für allgemeine Abfragen genutzt werden: Wenn Sie nicht Millionen von Datensätzen abrufen, ist die Geschwindigkeit der Abfrage dieselbe wie bei Datenbanken mittlerer Größe (10–15 Gb).
Dies ist nicht das Ende dieses Experiments: Wir beabsichtigen, einige Abfragen auszuführen, zusätzliche Statistiken zu sammeln und in Kürze einen ausführlicheren Bericht zu veröffentlichen. Bleiben Sie dran.
Kontakte
Senden Sie alle Ihre Fragen und Anfragen an [email protected]