Каковы накладные расходы для varchar (n)?

Я хотел попросить значение этого фрагмента из Postgres doc относительно varchar(n) type:

  

Требование к хранению короткой строки (до 126 байтов) - 1 байт   плюс фактическая строка, которая включает пробел в корпусе   характера. Более длинные строки имеют 4 байта служебных данных вместо 1.

Предположим, что у меня есть поле varchar(255). И теперь следующие утверждения:

  • Если это поле содержит строку в 10 байт, то служебные данные - 1 байт. Таким образом, строка будет использовать 11 байтов.
  • Если поле содержит строку с использованием 140 байтов, то служебные данные составляют 4 байта. Таким образом, строка будет использовать 144 байта.

Являются ли эти утверждения выше истинными? Здесь кто-то понимает документ так же, как и я, но здесь кто-то утверждает, что служебные данные всегда 4 байта здесь ?

12 голосов | спросил keypress 7 Jpm1000000pmThu, 07 Jan 2016 16:20:06 +030016 2016, 16:20:06

1 ответ


15

Неудивительно, что руководство правильно. Но есть еще кое-что.

Во-первых, размер на диске (в любой таблице , даже если он фактически не хранится на диске) может отличаться от размера в памяти . На диске служебные данные для коротких varchar значений до 126 байтов сводятся к 1 байт , как указано в руководство. Но служебные в памяти всегда 4 байта (после выделения отдельных значений).

То же самое верно для text, varchar, varchar(n) или char(n) - за исключением того, что char(n) заполняется пустым символом n, и вы обычно не хотите его использовать , его эффективный размер может по-прежнему меняться в многобайтовых кодировках, потому что n обозначает максимум символов, а не байтов:

  

строки длиной до n (не байты).

Все они используют внутри varlena.
"char" (с двойными кавычками) - это другое существо и всегда занимает один байт.

Тест с 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

Как вы можете видеть:

  • 3-байтовая строка 'foo' занимает 4 байта на диске и 7 байт в ОЗУ (так что 1 байт против 4 байтов служебных данных).
  • 140-байтовая строка «123 ...» занимает 144 байта как на диске, так и в ОЗУ (так всегда 4 байта служебных данных).
  • Хранение integer не имеет накладных расходов (но у него есть требования к выравниванию, которые могут налагать заполнение).
  • Строка содержит дополнительные служебные данные из 24 байтов для заголовка набора (плюс дополнительные 4 байта на кортеж для указателя элемента в заголовке страницы).
  • И последнее, но не менее важное: служебные данные небольшого varchar по-прежнему остаются 1 байт, пока он не был извлечен из строки - как видно из размера строки. (Вот почему иногда бывает немного быстрее выбрать всю строку.)

по теме:

ответил Erwin Brandstetter 7 Jpm1000000pmThu, 07 Jan 2016 18:46:02 +030016 2016, 18:46:02

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132