Sans surprise, le manuel est juste. Mais il y a plus que cela.
D'une part, la taille sur le disque (dans n'importe quelle table , même lorsqu'elle n'est pas réellement stockée sur le disque) peut être différente de la taille en mémoire . Sur le disque, la surcharge pour les varchar
valeurs courtes jusqu'à 126 octets est réduite à 1 octet comme indiqué dans le manuel. Mais la surcharge en mémoire est toujours de 4 octets (une fois les valeurs individuelles extraites).
La même chose est vrai pour text
, varchar
, varchar(n)
ouchar(n)
- sauf que char(n)
est complétée par des blancs à n
caractères et vous ne voulez pas l' utiliser normalement. Sa taille effective peut toujours varier dans les codages multi-octets car n
dénote un maximum de caractères, pas d'octets:
les chaînes peuvent contenir jusqu'à des n
caractères (et non des octets).
Tous les utilisent en varlena
interne.
"char"
(avec des guillemets doubles) est une créature différente et occupe toujours un seul octet.
Les littéraux de chaîne non typés ( 'foo'
) ont une surcharge d'un seul octet. À ne pas confondre avec les valeurs tapées!
Testez avec 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
Comme vous pouvez le voir:
- La chaîne de 3 octets «foo» occupe 4 octets sur le disque et 7 octets dans la RAM (donc 1 octet contre 4 octets de surcharge).
- La chaîne de 140 octets «123 ...» occupe 144 octets sur le disque et dans la RAM (donc toujours 4 octets de surcharge).
- Le stockage de
integer
n'a pas de surcharge (mais il a des exigences d'alignement qui peuvent imposer un remplissage).
- La ligne a une surcharge supplémentaire de 24 octets pour l'en-tête de tuple (plus 4 octets supplémentaires par tuple pour le pointeur d'élément dans l'en-tête de page).
- Et dernier point mais non des moindres: le surdébit du petit
varchar
n'est toujours que de 1 octet alors qu'il n'a pas été extrait de la ligne - comme on peut le voir sur la taille de la ligne. (C'est pourquoi il est parfois un peu plus rapide de sélectionner des lignes entières.)
En relation: