Typ danych uuid
jest idealnie nadaje się do tego zadania. Zajmuje tylko 16 bajtów w przeciwieństwie do 37 bajtów w pamięci RAM dla reprezentacji varchar
lub text
. (Lub 33 bajty na dysku, ale w wielu przypadkach liczba nieparzysta wymagałaby uzupełnienia, aby efektywnie osiągnąć 40 bajtów.) A ten uuid
typ ma jeszcze więcej zalet.
Przykład:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Szczegóły i więcej wyjaśnień:
Możesz rozważyć inne (tańsze) funkcje haszujące, jeśli nie potrzebujesz komponentu kryptograficznego md5, ale wybrałbym md5 dla twojego przypadku użycia (głównie tylko do odczytu).
Słowo ostrzeżenia : W twoim przypadku ( immutable once written
) funkcjonalnie zależna (pseudo-naturalna) PK jest w porządku. Ale to samo będzie bolało,text
gdy możliwe są aktualizacje . Pomyśl o poprawieniu literówki: PK i wszystkie zależne indeksy, kolumny FK dozens of other tables
i inne odniesienia również musiałyby się zmienić. Nadęty tabel i indeksów, problemy z blokowaniem, powolne aktualizacje, utracone referencje, ...
Jeśli text
może się zmienić podczas normalnej pracy, lepszym wyborem byłby zastępczy PK . Proponuję bigserial
kolumnę (zakres -9223372036854775808 to +9223372036854775807
- to dziewięć kwintillion dwieście dwadzieścia trzy biliard trzysta siedemdziesiąt dwa tryliony trzydzieści sześć coś miliard ) odrębnych wartości billions of rows
. W każdym razie może to być dobry pomysł : 8 zamiast 16 bajtów na dziesiątki kolumn i indeksów FK!). Lub losowy UUID dla znacznie większych liczności lub systemów rozproszonych. Zawsze można przechowywać powiedział md5 (a uuid
) dodatkowo do szybko znaleźć wiersze w tabeli głównej z oryginalnego tekstu. Związane z:
Jeśli chodzi o twoje zapytanie :
Aby odpowiedzieć na komentarz @ Daniela : Jeśli wolisz reprezentację bez łączników, usuń łączniki do wyświetlenia:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Ale nie zawracałbym sobie głowy. Domyślna reprezentacja jest w porządku. A problemem tak naprawdę nie jest tutaj reprezentacja.
Jeśli inne strony powinny mieć inne podejście i wrzucać ciągi bez łączników do miksu, nie stanowi to również problemu. Postgres akceptuje kilka rozsądnych reprezentacji tekstowych jako dane wejściowe dla uuid
. Dokumentacja :
PostgreSQL akceptuje także następujące alternatywne formy wprowadzania danych: użycie wielkich liter, standardowy format otoczony nawiasami klamrowymi, pomijanie niektórych lub wszystkich łączników, dodawanie łącznika po dowolnej grupie czterech cyfr. Przykładami są:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Co więcej, md5()
funkcja zwraca text
, należałoby użyć decode()
do konwersji bytea
i domyślnej reprezentacji , które brzmi:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Musisz encode()
ponownie uzyskać oryginalną reprezentację tekstu:
SELECT encode(my_md5_as_bytea, 'hex');
Co więcej, wartości przechowywane jako bytea
zajmowałyby 20 bajtów w pamięci RAM (i 17 bajtów na dysku, 24 z wypełnieniem ) z powodu wewnętrznego varlena
obciążenia , co jest szczególnie niekorzystne dla rozmiaru i wydajności prostych indeksów.
Wszystko działa na korzyść uuid
tutaj.
text
kolumnach - nawet jeśli w ogóle nie jest to „tekst”.SELECT encode(decode('tZmffOd5Tbh8yXaVlZfRJQ==', 'base64'), 'hex')::uuid;
.uuid
to 16-bajtowy typ, który nie może przechowywać wyników żadnego algorytmu SHA produkującego od 160 do 512 bitów. Nie ma podobnego typu, który mieści się w standardowej dystrybucji Postgres. Możesz utworzyć jeden ... W przeciwnym razie domyślniebytea
- tak jak robi to pg_crypto .Chciałbym zapisać MD5 w kolumnie
text
lubvarchar
. Nie ma różnicy w wydajności między różnymi typami danych znaków. Możesz ograniczyć długość wartości md5,varchar(xxx)
upewniając się, że wartość md5 nigdy nie przekracza określonej długości.Duże listy IN zwykle nie są naprawdę szybkie, lepiej zrobić coś takiego:
Inną opcją, o której mówi się, że jest szybsza, jest użycie tablicy:
Ponieważ porównujesz tylko dla równości, zwykły indeks BTree powinien być w porządku. Oba zapytania powinny mieć możliwość korzystania z takiego indeksu (szczególnie jeśli wybierają tylko niewielką część wierszy.
źródło
bit
typu, więc nie mogę tego komentować. Biorąc pod uwagę oczekiwaną liczbę wierszy, sugestia Erwina wydaje się lepsza ze względu na oszczędność miejsca, którą uzyskujesz dzięki przechowywaniu tego jako UUIDInną opcją jest użycie 4 kolumn INTEGER lub 2 BIGINT.
źródło