Qual è l'overhead per varchar (n)?


15

Volevo chiedere il significato di questo frammento dal documento di Postgres per quanto riguarda il varchar(n)tipo:

Il requisito di archiviazione per una stringa breve (fino a 126 byte) è 1 byte più la stringa effettiva, che include il riempimento dello spazio in caso di carattere. Le stringhe più lunghe hanno 4 byte di sovraccarico invece di 1.

Supponiamo che io abbia un varchar(255)campo. E ora, le seguenti dichiarazioni:

  • Se questo campo contiene una stringa di 10 byte, l'overhead è di 1 byte. Quindi la stringa utilizzerà 11 byte.
  • Se il campo contiene una stringa che utilizza 140 byte, l'overhead è di 4 byte. Quindi la stringa utilizzerà 144 byte.

Queste affermazioni sono vere? Qui qualcuno capisce il documento allo stesso modo di me, ma qui qualcuno afferma che il sovraccarico è sempre di 4 byte qui ?

Risposte:


19

Non sorprende che il manuale sia giusto. Ma c'è di più.

Per uno, le dimensioni su disco (in qualsiasi tabella , anche quando non sono effettivamente archiviate su disco) possono essere diverse dalle dimensioni in memoria . Sul disco, l'overhead per varcharvalori brevi fino a 126 byte è ridotto a 1 byte, come indicato nel manuale. Ma l'overhead in memoria è sempre di 4 byte (una volta estratti i singoli valori).

Lo stesso vale per il text, varchar, varchar(n)ochar(n) - se non che char(n)è vuota imbottite di ncaratteri e che normalmente non si desidera utilizzarlo. La sua dimensione effettiva può ancora variare nelle codifiche multi-byte perché nindica un massimo di caratteri, non byte:

stringhe fino a ncaratteri (non byte) di lunghezza.

Tutti usano varlenainternamente.
"char"(con virgolette doppie) è una creatura diversa e occupa sempre un singolo byte.
I letterali stringa non tipizzati ( 'foo') hanno un overhead a byte singolo. Da non confondere con i valori digitati!

Prova con pg_column_size().

CREATE TEMP TABLE t (id int, v_small varchar, v_big varchar);
INSERT INTO t VALUES (1, 'foo', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');

SELECT pg_column_size(id)        AS id
     , pg_column_size(v_small)   AS v_small
     , pg_column_size(v_big)     AS v_big
     , pg_column_size(t)         AS t
FROM   t
UNION ALL  -- 2nd row measuring values in RAM
SELECT pg_column_size(1)
     , pg_column_size('foo'::varchar)
     , pg_column_size('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar)
     , pg_column_size(ROW(1, 'foo'::varchar, '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar));

 id | v_small | v_big |  t
----+---------+-------+-----
  4 |       4 |   144 | 176
  4 |       7 |   144 | 176

Come potete vedere:

  • La stringa di 3 byte 'pippo' occupa 4 byte sul disco e 7 byte nella RAM (quindi 1 byte contro 4 byte di sovraccarico).
  • La stringa di 140 byte '123 ...' occupa 144 byte sia sul disco che nella RAM (quindi sempre 4 byte di overhead).
  • Lo stoccaggio di integernon ha costi generali (ma ha requisiti di allineamento che possono imporre imbottitura).
  • La riga ha un sovraccarico aggiuntivo di 24 byte per l'intestazione della tupla (più altri 4 byte per tupla per il puntatore dell'elemento nell'intestazione della pagina).
  • E, ultimo ma non meno importante: l'overhead del piccolo varcharè ancora solo 1 byte mentre non è stato estratto dalla riga, come si può vedere dalle dimensioni della riga. (Ecco perché a volte è più veloce selezionare intere righe.)

Relazionato:


1
Quel sovraccarico di 1 byte è ancora 1 byte nell'indice?
dvtan il

1
@dtgq: un indice memorizza i dati proprio come una tabella, quindi sì.
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.