La ricerca dell'indice sarebbe notevolmente più veloce con char vs varchar quando tutti i valori sono 36 caratteri


30

Ho uno schema legacy (dichiarazione di non responsabilità!) Che utilizza un ID generato basato su hash per la chiave primaria per tutte le tabelle (ce ne sono molte). Un esempio di tale ID è:

922475bb-ad93-43ee-9487-d2671b886479

Non vi è alcuna speranza di cambiare questo approccio, tuttavia le prestazioni con accesso all'indice sono scarse. Mettendo da parte la miriade di ragioni per cui questo potrebbe essere, c'è una cosa che ho notato che sembrava non ottimale - nonostante tutti i valori id in tutti i numerosi tavoli che sono esattamente 36 caratteri di lunghezza, il tipo di colonna è varchar(36), non è char(36) .

La modifica dei tipi di colonna a lunghezza fissa char(36)offrirebbe vantaggi significativi in termini di prestazioni dell'indice, oltre al piccolissimo aumento del numero di voci per pagina dell'indice, ecc.?

Cioè Postgres ha prestazioni molto più veloci quando si tratta di tipi a lunghezza fissa che con tipi a lunghezza variabile?

Si prega di non menzionare il minuscolo risparmio di spazio di archiviazione, che non sarà rilevante rispetto all'intervento chirurgico necessario per apportare la modifica alle colonne.

Risposte:


40

No. Nessun guadagno . Il manuale afferma esplicitamente :

Suggerimento: non vi è alcuna differenza di prestazioni tra questi tre tipi , a parte un maggiore spazio di archiviazione quando si utilizza il tipo con riempimento vuoto e alcuni cicli CPU aggiuntivi per controllare la lunghezza quando si archivia in una colonna con vincoli di lunghezza. Sebbene presenti character(n)vantaggi in termini di prestazioni in alcuni altri sistemi di database, PostgreSQL non offre tali vantaggi; infatti, di character(n)solito è il più lento dei tre a causa dei suoi costi di archiviazione aggiuntivi. Nella maggior parte delle situazioni text o character varyingdovrebbe essere usato invece .

Enorme enfasi sulla mia.

char(n)è un tipo in gran parte obsoleto e inutile. Resta con varchar(n). Se non è necessario imporre la lunghezza, varcharo textsarebbe un po 'più veloce. Non sarai in grado di misurare una differenza.

Inoltre, se tutte le stringhe sono esattamente lunghe 36 caratteri, non c'è spazio di memorizzazione in entrambi i modi, nemmeno minuscolo. Entrambi hanno esattamente le stesse dimensioni sul disco e nella RAM. Puoi provare con pg_column_size()(su un'espressione e su una colonna della tabella).

Relazionato:

Non hai chiesto altre opzioni , ma ne citerò due:

  1. COLLATION- a meno che non si stia eseguendo il proprio DB con le regole di confronto "C" . La collazione è spesso trascurata e forse costosa. Dato che le tue stringhe non sembrano significative in un linguaggio naturale, probabilmente non ha senso seguire le COLLATIONregole. Relazionato:

    Ampio benchmark che confronta (tra l'altro) l'effetto delle COLLATE "C"prestazioni:

  2. UUID , ovviamente. La stringa appare sospettosamente come un UUID (32 cifre esadecimali più 4 delimitatori). Sarebbe molto più efficiente archiviarli comeuuidtipo di datieffettivo, che è più veloce in più modi e occupa solo 16 byte - rispetto a 37 byte nella RAM per unochar(36)ovarchar(36)(archiviati senza delimitatori, solo il 32 che definisce il carattere), o 33 byte sul disco. Ma il padding di allineamento comporterebbe 40 byte in entrambi i casi in molti casi.)COLLATIONSarebbe irrilevante anche per iluuidtipo di dati.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Questo può essere utile (ultimi capitoli):

    Guarda anche:


questo significa che un carattere con vincolo di lunghezza / varchar (n) impiegherà i cicli della CPU per controllare il vincolo mentre il campo di testo a lunghezza variabile memorizzerebbe il testo separatamente in un modo meno accessibile rispetto al carattere, che vince in questo scenario ed è questa vittoria vale anche la pena considerare per esempio 10 milioni di righe con un pezzo di testo
PirateApp,

1
@PirateApp: char(n)quasi mai vince sotto nessun punto di vista. Non usarlo. I tipi di dati texte varchar(senza modificatore di lunghezza) sono binari compatibili e condividono le stesse caratteristiche prestazionali. Ci sono ragioni storiche per cui entrambi possono coesistere in Postgres. Internamente, textè il tipo "preferito" tra i tipi di stringa (che può influenzare la risoluzione del tipo di funzione). I cicli della CPU per applicare a varchar(n)malapena la materia. Usa una limitazione di lunghezza quando ne hai bisogno . Nel caso a portata di mano uuidè il vero vincitore.
Erwin Brandstetter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.