Wieso nimmt Firebird sich nicht den verfügbaren Hauptspeicher, so dreist wie es
MSSQL macht?! Es gibt sicher nichts schnelleres, als alles was geht im Hauptspeicher zu puffern! Vielleicht weil
FB auch eine süße, kleine embedded
DB ist und das einfach in den Köpfen der Entwickler rumwabert? Welches Feature macht da den Unterschied?
Gerne ein wenig Erklärung dazu: stell dir mal vor du hast eine 100GB
DB mit 100 tabellen die jeweils 1GB belegen, deine Abfrage beziehen sich aber ausschliesslich auf Daten einer Tabelle, deren Rohdaten 1GB belegen (nennt man bei firebird datenpages, indexpages, und noch ein wenig krams aus kleineren Systemtabellen und transaktionsdaten).
Ein ganz banaler select count() auf dieser Tabelle kann von Firebird nur dann beantwortet werden, wenn jede Recordversion auf sichtbarkeit/gelöscht geprüft wurde für den Transaktionskontext, aus dem das aufgerufen wurde. Repeatableread connections können zB andere Anzahlen sehen als Readcommitted usw.
Wie behandelt firebird nun deine Abfrage:
Es lädt sich alle erforderlich Pages von der Platte in den
RAM und im
RAM wird das dann auseinandergefrickelt.
Nehmen wir an, deine
DB benutzt den Superserver 2x oder 30, bei dem es einen gemeinsamen Cache für alle gibt. In Tools wie IBExpert siehst du dann das zB der Wert Reads beim ersten Zugriff ziemlich hoch ist, reads sind die pages, die von platte in den
RAM geladen wurden. Gehen wir mal davon aus das du 16k Pagegröße beim Anlegen der
DB benutzt hast und als cache buffers 100000 eingestellt hast. Damit weiss firebird, es kann bis zu 1,6 GB
RAM fest benutzen. Deine komplette Tabelle belegt aber gerade mal 1GB, also ca 65000 pages. In den Reads wirst du sehen, das zu deinem
SQL 65000 pages in reads stehen und die wurden auch im Speicher in etwa nun physikalisch belegt +x für das was der prozess eh braucht.
Warum aber Firebird irgendwas in den
RAM packen sollte was keiner wissen will, erschliesst sich mir nicht.
Nun kommt der zweite Client und will auch noch mal einen Count wissen. Was passiert? Firebird nimmt das
SQL entgegen,analysiert dazu wie schon beim ersten Mal die erforderlichen Pages und merkt beim Superserver, huch, die sind ja schon im Speicher, also brauch nix nachgeladen werden, sondern es kann gleich im
RAM losgehen. In den Reads liest du nun übrigens auch 0 , d.h. alles was gebraucht wird, war schon im
ram.
Solange nicht alle zugewiesenen CachePages belegt sind und für andere Pages weiterer
RAM gebraucht wird, wird firebird superserver die daten auch nicht mehr aus dem
ram rausschmeissen, es sei denn, die letzte Connection meldet sich dann auch noch ab und es ist kein Client mehr verbunden. Sobald jemand dann neu kommt geht das wieder von vorne los, wenn man das vermeiden möchte lässt man immer einen client aktiv.
Es ergibt aber immer noch keinen sinn, die nächten 100GB
RAM mit Tabellen vollzumüllen, die keiner braucht. Schon gar nicht auf einer Maschine, die eben nicht 1GB
RAM frei hat (Bedenke, es gab bis vor einigen Jahren und auch heute noch 32bit Versionen von Datenbanksystemen, die bei 2GB dicke backen machen. Firebird kann auch als 32bit Version im Gegensatz zum Beispiel zu MS
Access mdb auch eine 10TB Datenbankdatei öffnen und sauber verwalten, aber prozesstechnisch gehen da nicht mehr als 2GB
RAM in der 32 Bit Welt).
Und spätestens bei der 2TB Datenbank könnte es eng werden mit alles im
RAM.
Sicherlich erfordern komplexe Abfrage mit group by etc einiges mehr an
RAM, Global Temp Tables arbeiten komplett im
RAM oder Recordversionen, Tempspace ist zunächst
ram, wenn aber mehr gebraucht wird, ausgelagert, aber das ist alles konfigurierbar, wen man es braucht und der
RAM da ist. Firebird läuft aber auch heute noch auf minimal Hardware mit vollem Funktionsumfang und insbesondere mit Betriebssystemen wie Linux ist das sehr gut skalierbar. Und die Standard Konfiguration ist nicht so schlecht, mit falschen Parametern kann man auch viel falsch machen.
Zu viel
RAM muss übrigens kein Vorteil sein, weil dann ggf zu ändernde Pages wesentlich länger im
RAM bleiben und erst mit dem Commit auf den Datenträger geschrieben werden (das aber eben mit forced writes in einer extrem robusten reihenfolge, die bei windows ohne forced writes verändert wird und ein servercrash ohne forced writes auf windows gerne mal in einer kaputten datenbank enden kann. Unter linux kann ich das auf filesystemeben vermeiden und deutlich besser optimieren, als das was windows in ntfs das selber macht. Bei Dialogsoftware kommt dann unglücklicherweise beim speichern eine Wartezeit zustande, die der Anwender merkt, aber bei kleinerem Cache wären die Pages ggf zum Teil schon vorher wieder auf dem Datenträger.
Microsoft
SQL Server ist von Microsoft und hat halt unter Windows die Angewohnheit zu sagen, der Rechner gehört mir und nur wenn was übrig bleibt, kann das jemand anders haben.
Welche Tricks da laufen weiß ich nicht, aber ein von mir mal auf Linux gemachter tpc Benchmark mit Firebird30 und
MSSQL auf Linux brachte eine überraschend ähnliche Leistung, bei der Firebird aber sogar noch besser war, der erreichte tpc Wert für den
MSSQL Server auf dieser Maschine (Kosten ca 4000€) aber laut Vergleichstabelle dieses tpc benchmarks in Bereichen lag, die ansonsten kein aktueller Windows
mssql server unter 40000 US$ gebracht hat.
Leider hab ich das nicht gut dokumentiert und müsste das ggf ncoh mal zusammensuchen, aber wer weiß, wenn ich zeit hab mach ich das noch mal.
Wie schon geschildert,
MSSQL mag scheinbar mit dataset/datasource/lookup/master-detail Delphi Applikationen wie besser klarkommen, es ist aber für optimierte Anwendung nicht annähernd 4-10 mal schneller.
btw:
RAM und x4 m.2 SSDs sind vom Speed her nicht mehr so unterschiedlich,
Ram ist bei größeren Blöcken oft gerade mal doppelt so schnell, wenn überhaupt. Mach einfach mal benchmarktests auf ssd und auf Ramdisk, das ist je nach Aufgabenstellung meiste nähere aneinander als man erwarten würde.