Die Unterschiede zwischen VARCHAR- und INTEGER-Feldern in Schlüsseln
Ich verwende Integer-IDs als Primärschlüssel in meinen Tabellen. Was wäre, wenn ich stattdessen varchar-Felder verwenden würde? Werde ich in diesem Fall an Leistung verlieren, besonders bei großen Tabellen? Werden Joins immer noch so schnell funktionieren wie bei der Integer-Spalte?
Ihre Leistung sollte mit varchars oder Integers ungefähr gleich sein. Firebird vergleicht Indexschlüssel immer byteweise, und nur der signifikante Teil des Werts wird gespeichert.
Ein Einzelfeld-Schlüssel wird zuerst in einen der drei kanonischen Typen konvertiert: String mit Kollation, Double Precision und (leider) 64-Bit-Integer. Datumsangaben werden zu Double-Precision-Gleitkommazahlen.
Strings, die eine andere Kollation als ihren Bytewert haben, werden in ihr Kollationsformat konvertiert. Das ist eine Art schwarze Kunst und vergrößert die Länge des Strings, aber das Ergebnis ist, dass der String seinen korrekten Platz findet, wenn er mit anderen Strings derselben Kollation sortiert wird. ‘A’, ‘a’, ‘â’, ‘á’, ‘Ă’, ‘ã’, ‘ä’, ‘å’, ‘ă’, ‘ą’, ‘Ā’ erscheinen alle an ihren vorgesehenen Stellen. (Entschuldigung, was das mit Ihrem E-Mail-Client gemacht hat …. in meinem sind das elf Varianten von ‘A’.) Nachgestellte Leerzeichen sind nicht im Schlüssel enthalten.
Die Double-Precision-Zahl wird so umgewandelt, dass auch sie byteweise sortiert - grob gesagt: Vorzeichen invertieren, dann Exponent, dann Mantisse, wobei nachgestellte Nullen abgeschnitten werden.
Abhängig von der Endianness von 64-Bit-Integern auf dem Computer werden auch diese so umgewandelt, dass sie byteweise verglichen werden. Das mag wie eine Optimierung erscheinen, aber Indexschlüssel werden nicht an natürlichen Grenzen gespeichert und unterliegen einer Präfixkomprimierung, sodass es keine Möglichkeit gibt, einen größeren Vergleich als Byte für Byte zu verwenden.
Verbundschlüssel funktionieren ähnlich. Jeder Teil wird in seinen Indexschlüsseltyp konvertiert und auf ein Vielfaches von 4 Bytes aufgefüllt. Nach jeweils vier Bytes fügt Firebird ein Byte mit der Position des aktuellen Felds des Schlüssels hinzu. So würde ein Index auf LastName, FirstName, ZodiacSign als 1Harr1ison2Ann 3Gemi3ni ausgegeben. Dies vermeidet die Peinlichkeit, Damnation mit Dam nation zu verwechseln.
Warum habe ich oben „(leider)“ gesagt? Weil ein einziges Format für Zahlen es Firebird ermöglicht, die Größe von Zahlen zu ändern, ohne die Indizes darauf neu zu erstellen. Aber als Borland 64-Bit-Integers wieder einführte - InterBase hatte 64-Bit-Integers von Anfang an auf Vaxes - kam ein kluger Kopf auf die Idee, dass Double Precision 56 Bit Präzision hat und 64-Bit-Integers 64 Bit. Andererseits sind Firebird-Indizes darauf ausgelegt, etwas Ungenauigkeit zu verarbeiten … oder die restlichen 8 Bits könnten ans Ende angehängt werden … wie auch immer. Sie müssen also Indizes neu erstellen, wenn Sie von Numeric/Decimal 9 auf Numeric/Decimal 12 wechseln. Traurig.
„Präfixkomprimierung?“ Beim Speichern eines Schlüssels, der nicht der erste auf einer Seite oder der erste nach einem Sprung auf der Seite ist, betrachtet Firebird den vorhergehenden Schlüssel und schneidet den Teil des Anfangs des nächsten Schlüssels ab, der mit seinem Vorgänger übereinstimmt, und hängt die Länge des abgeschnittenen Teils an den Anfang. So werden die Strings „AAAA“, „AAAB“, „AAAC“, „AABC“ zu
„AAAA“, „3B“, „3C“ und „2BC“. Es gibt ein Problem mit einigen GUID-Formaten, die den volatilen Teil der Zahl zuerst setzen, gefolgt vom festen Teil. Das untergräbt die Präfixkomprimierung und vergrößert die Indizes.
„Sprung?“ - Präfixkomprimierung reduziert die Größe von Indizes erheblich, reduziert I/O, erfordert aber das Lesen über die gesamte Seite, um den Schlüssel zu entschlüsseln. Das ist mit 1K-Seiten in Ordnung, aber bei größeren Seitengrößen war die Berechnung inakzeptabel. Daher hat jede Indexseite jetzt einen eigenen Index, der auf die Offsets der unkomprimierten Einträge zeigt. Dieser Index wird Sprungvektor genannt.
Ann Harrision