Неудивительно, что руководство является правильным. Но это еще не все.
С одной стороны, размер на диске (в любой таблице , даже если он не хранится на диске) может отличаться от размера в памяти . На диске служебная информация для коротких varchar
значений до 126 байтов уменьшается до 1 байта, как указано в руководстве. Но накладные расходы в памяти всегда составляют 4 байта (после извлечения отдельных значений).
То же самое относится и к text
, varchar
, varchar(n)
илиchar(n)
- за исключением того, что char(n)
оно дополняется пробелами до n
символов и обычно не хотят , чтобы использовать его. Его эффективный размер все еще может варьироваться в многобайтовых кодировках, потому что n
обозначает максимум символов, а не байтов:
строки длиной до n
символов (не байтов).
Все они используют varlena
внутри страны.
"char"
(с двойными кавычками) - другое существо и всегда занимает один байт.
Нетипизированные строковые литералы ( 'foo'
) имеют накладные расходы в один байт. Не путать с введенными значениями!
Тест с 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
Как вы видете:
- Трехбайтовая строка 'foo' занимает 4 байта на диске и 7 байтов в ОЗУ (таким образом, 1 байт против 4 байтов служебных данных).
- 140-байтовая строка «123 ...» занимает 144 байта как на диске, так и в оперативной памяти (поэтому всегда 4 байта служебных данных).
- Хранение
integer
не имеет накладных расходов (но оно имеет требования к выравниванию, которые могут накладывать отступы).
- Строка имеет дополнительные служебные данные в 24 байта для заголовка кортежа (плюс дополнительные 4 байта на кортеж для указателя элемента в заголовке страницы).
- И последнее по порядку, но не по значению:
varchar
размер заголовка по- прежнему составляет всего 1 байт, пока он не извлечен из строки - как видно из размера строки. (Вот почему иногда бывает немного быстрее выделять целые строки.)
Связанный: