Il tipo di dati uuid
è perfettamente adatto per l'attività. Occupa solo 16 byte anziché 37 byte nella RAM per la rappresentazione varchar
o text
. (O 33 byte sul disco, ma il numero dispari richiederebbe il riempimento in molti casi per renderlo efficacemente 40 byte.) E il uuid
tipo ha alcuni vantaggi in più.
Esempio:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Dettagli e ulteriori spiegazioni:
Potresti considerare altre funzioni di hashing (più economiche) se non hai bisogno del componente crittografico di md5, ma andrei con md5 per il tuo caso d'uso (principalmente di sola lettura).
Un avvertimento : per il tuo caso ( immutable once written
) un PK funzionalmente dipendente (pseudo-naturale) va bene. Lo stesso sarebbe un dolore in cui text
sono possibili aggiornamenti . Pensa a correggere un refuso: anche il PK e tutti gli indici dipendenti, le colonne FK dozens of other tables
e altri riferimenti dovrebbero cambiare. Gonfiore di tabelle e indici, problemi di blocco, aggiornamenti lenti, riferimenti persi, ...
Se text
può cambiare durante il normale funzionamento, un PK surrogato sarebbe una scelta migliore. Suggerisco una bigserial
colonna (intervallo -9223372036854775808 to +9223372036854775807
- che è nove quintilioni duecentoventitre tre trecento settantadue trilioni trentasei qualcosa miliardi ) valori distinti per billions of rows
. Potrebbe essere una buona idea in ogni caso: 8 invece di 16 byte per dozzine di colonne e indici FK!). O un UUID casuale per cardinalità o sistemi distribuiti molto più grandi. Puoi sempre memorizzare detto md5 (as uuid
) in aggiunta per trovare rapidamente le righe nella tabella principale dal testo originale. Relazionato:
Per quanto riguarda la tua query :
Per rispondere al commento di @ Daniel : se preferisci una rappresentazione senza trattini, rimuovi i trattini per la visualizzazione:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Ma non mi preoccuperei. La rappresentazione predefinita va bene. E il problema non è proprio la rappresentazione qui.
Se le altre parti dovrebbero avere un approccio diverso e lanciare stringhe senza trattini nel mix, anche questo non è un problema. Postgres accetta diverse rappresentazioni testuali ragionevoli come input per a uuid
. La documentazione :
PostgreSQL accetta anche i seguenti moduli alternativi per l'input: uso di caratteri maiuscoli, il formato standard circondato da parentesi graffe, omettendo alcuni o tutti i trattini, aggiungendo un trattino dopo qualsiasi gruppo di quattro cifre. Esempi sono:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Cosa c'è di più, le md5()
restituisce la funzione text
, si può usare decode()
per convertire in bytea
e la rappresentazione di default che è:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Dovresti di encode()
nuovo ottenere la rappresentazione del testo originale:
SELECT encode(my_md5_as_bytea, 'hex');
Per finire, i valori memorizzati bytea
occuperebbero 20 byte nella RAM (e 17 byte sul disco, 24 con riempimento ) a causa del sovraccarico internovarlena
, che è particolarmente sfavorevole per le dimensioni e le prestazioni di indici semplici.
Tutto funziona a favore di un uuid
qui.