Der Datentyp uuid
ist perfekt für die Aufgabe geeignet. Es belegt nur 16 Bytes im Gegensatz zu 37 Bytes im RAM für die varchar
oder text
-Darstellung. (Oder 33 Bytes auf der Festplatte, aber die ungerade Anzahl würde in vielen Fällen ein Auffüllen erfordern, um 40 Bytes effektiv zu machen .) Und der uuid
Typ hat einige weitere Vorteile.
Beispiel:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Details und weitere Erklärung:
Sie könnten andere (billigere) Hashing-Funktionen in Betracht ziehen, wenn Sie die kryptografische Komponente von md5 nicht benötigen, aber ich würde mich für Ihren Anwendungsfall für md5 entscheiden (meistens schreibgeschützt).
Ein Wort der Warnung : Für Ihren Fall ( immutable once written
) ist eine funktional abhängige (pseudo-natürliche) PK in Ordnung. Aber das gleiche wäre ein Schmerz, bei dem Updates text
möglich sind. Denken Sie daran, einen Tippfehler zu korrigieren: Die PK und alle abhängigen Indizes, FK-Spalten in dozens of other tables
und andere Verweise müssten sich ebenfalls ändern. Tabelle und Index aufgebläht, Sperrprobleme, langsame Aktualisierungen, verlorene Referenzen, ...
Wenn text
sich im Normalbetrieb etwas ändern kann, ist ein Ersatz-PK die bessere Wahl. Ich schlage eine bigserial
Spalte (Bereich -9223372036854775808 to +9223372036854775807
- das sind neun Billionen zweihundertdreiundzwanzig Billionen dreihundertzweiundsiebzig Billionen sechsunddreißig Milliarden ) mit unterschiedlichen Werten für vor billions of rows
. Könnte auf jeden Fall eine gute Idee sein : 8 statt 16 Bytes für Dutzende von FK-Spalten und -Indizes!). Oder eine zufällige UUID für viel größere Kardinalitäten oder verteilte Systeme. Sie können immer der Speicher md5 (wie uuid
) zusätzlich Reihen in der Haupttabelle schnell aus dem ursprünglichen Text zu finden. Verbunden:
Wie für Ihre Frage :
An @ Daniels Kommentar adressieren : Wenn Sie eine Darstellung ohne Bindestriche bevorzugen, entfernen Sie die Bindestriche für die Anzeige:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Aber ich würde mich nicht darum kümmern. Die Standarddarstellung ist in Ordnung. Und das Problem ist wirklich nicht die Darstellung hier.
Wenn andere Parteien einen anderen Ansatz verfolgen und Strings ohne Bindestriche in die Mischung werfen sollten, ist dies ebenfalls kein Problem. Postgres akzeptiert mehrere sinnvolle Textdarstellungen als Eingabe für a uuid
. Die Dokumentation :
PostgreSQL akzeptiert auch die folgenden alternativen Formen für die Eingabe: Verwendung von Großbuchstaben, dem von geschweiften Klammern umgebenen Standardformat, Weglassen einiger oder aller Bindestriche und Hinzufügen eines Bindestrichs nach einer Gruppe von vier Ziffern. Beispiele sind:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Was mehr ist, gibt die md5()
Funktion zurück text
, die Sie decode()
zum Konvertieren verwenden würden, bytea
und die Standarddarstellung davon ist:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Sie müßten encode()
wieder die ursprüngliche Textdarstellung zu erhalten:
SELECT encode(my_md5_as_bytea, 'hex');
Um das Ganze abzurunden, bytea
belegen Werte, die gespeichert werden , 20 Bytes im RAM (und 17 Bytes auf der Festplatte, 24 mit Auffüllung ), aufgrund des internen varlena
Overheads , der für die Größe und Leistung einfacher Indizes besonders ungünstig ist.
Alles funktioniert zugunsten eines uuid
hier.
text
Spalten speichern - auch wenn es sich überhaupt nicht um einen "Text" handelt.SELECT encode(decode('tZmffOd5Tbh8yXaVlZfRJQ==', 'base64'), 'hex')::uuid;
.uuid
ist ein 16-Byte-Typ, der die Ergebnisse eines SHA-Algorithmus, der zwischen 160 und 512 Bit erzeugt, nicht speichern kann. Es gibt keinen ähnlichen Typ, der in die Standardverteilung von Postgres passt. Sie könnten eine erstellen ... Andernfalls wird standardmäßigbytea
- wie bei pg_crypto - verwendet.Ich würde das MD5 in einer
text
odervarchar
Spalte speichern . Es gibt keinen Leistungsunterschied zwischen den verschiedenen Zeichendatentypen. Möglicherweise möchten Sie die Länge der md5-Werte einschränken, indem Sievarchar(xxx)
sicherstellen, dass der md5-Wert niemals eine bestimmte Länge überschreitet.Große IN-Listen sind normalerweise nicht sehr schnell, es ist besser, so etwas zu tun:
Eine andere Option, die manchmal als schneller bezeichnet wird, ist die Verwendung eines Arrays:
Da Sie nur die Gleichheit vergleichen, sollte ein regulärer BTree-Index in Ordnung sein. Beide Abfragen sollten in der Lage sein, einen solchen Index zu verwenden (insbesondere wenn nur ein kleiner Bruchteil der Zeilen ausgewählt wird).
quelle
bit
Typ noch nie verwendet, daher kann ich dazu keinen Kommentar abgeben. Angesichts der erwarteten Anzahl von Zeilen scheint Erwins Vorschlag besser zu sein, da Sie Platz sparen, wenn Sie diese als UUID speichernEine andere Option ist die Verwendung von 4 INTEGER- oder 2 BIGINT-Spalten.
quelle