Чи займає значення порожнього стовпця той самий простір для зберігання, що і значення заповненого стовпця?


16

У мене є таблиця з 2 стовпцями. Тип обох стовпців встановлений уvarchar(38) . Якщо я створять рядок із порожнім значенням для одного з стовпців, чи займе це місце для зберігання, як якщо б значення не було порожнім?

Іншими словами, чи резервує MySQL місце для зберігання стовпця (залежно від його типу), коли буде створено рядок?

Відповіді:


11

З Фізичної Структури Innodb, пункт № 7 під REDUNDANT ROW_FORMAT

Значення SQL NULL зберігає один або два байти в каталозі записів. Крім того, значення SQL NULL резервує нульові байти в частині даних запису, якщо воно зберігається у стовпчику змінної довжини . У стовпчику фіксованої довжини він зберігає фіксовану довжину стовпця в частині даних запису.Збереження фіксованого простору для значень NULL дозволяє оновити стовпець від NULL до значення, яке не має NULL, зробити на місці, не викликаючи фрагментації сторінки індексу.

Від фізичної будови рядок Innodb, пункт №2 під КОМПАКТНИМИ ROW_FORMAT

Частина заголовка запису змінної довжини містить бітовий вектор для вказівки стовпців NULL. Якщо кількість стовпців в індексі, який може бути NULL, дорівнює N, бітовий вектор займає байти CEILING (N / 8) . (Наприклад, якщо є десь від 9 до 15 стовпців, які можуть бути NULL, бітовий вектор використовує два байти.) Стовпці, які мають NULL, не займають іншого простору, ніж біт у цьому векторі . Частина заголовка змінної довжини також містить довжини стовпців змінної довжини. Кожна довжина займає один або два байти, залежно від максимальної довжини стовпця. Якщо всі стовпці в індексі НЕ NULL і мають фіксовану довжину, заголовок запису не має частини змінної довжини.

Виходячи з цих точок позначень, ось яке NULLзначення приймає для зберігання стовпця

  • змінна довжина: значення NULL не займає місця в самому рядку
  • фіксована довжина: займає зарезервоване місце

Тепер ви повинні вирішити між використанням CHAR та VARCHAR через те, що вивів перший пункт

Збереження фіксованого простору для значень NULL дозволяє оновити стовпець від NULL до значення, яке не має NULL, зробити на місці, не викликаючи фрагментації сторінки індексу

Це запобіжить введенню фрагментації рядка, що йде вниз по дорозі після збереження даних, що не стосуються NULL. Це те, про що я говорив раніше стосовно MyISAM: Дивіться старий пост. Який вплив на ефективність використання CHAR проти VARCHAR на полі фіксованого розміру? .


Привіт Роландо, був ще один предмет, який я забув згадати, різниця у розподілі пам’яті між декларацією типу varchar (5) та varchar (100). Або справді покарання, понесене через перевитрату.
Крейг Ефрейн

@CraigEfrein Ви обов'язково додати розподіл пам'яті, що відповість. (BTW я вже схвалив вашу відповідь)
RolandoMySQLDBA

1
Штраф за перерозподіл трапляється, коли у вас є комплекс, для SELECTякого потрібно створити тимчасову таблицю. Якщо це можливо, він буде використовувати MEMORY, і конвертувати VARCHARв CHARдля таблиці TMP. Тепер VARCHAR(100)займає фіксовану 100 (або 300) байт, тим самим можливо сповільнюючи запит.
Рік Джеймс

@RolandoMySQLDBA, чи пояснюється поведінка у вашій відповіді, застосовне до форматів рядків MYSQL 5.7 DYNAMIC і COMPACT.
Дінеш Кумар

@DineshKumar Ці абзаци все ще містяться в документах 5.7 / 8.0. Будь ласка, зверніться до dev.mysql.com/doc/refman/5.7/en/innodb-row-format-dynamic.html для DYNAMIC.
RolandoMySQLDBA

8

Незалежно від довжини, яку ви визначаєте для своєї колонки varchar, місце для зберігання, яке використовується порожнім стовпцем, буде однаковим.

Типи CHAR і VARCHAR

введіть тут опис зображення

Це стосується лише простору, використовуваного стовпцем varchar, і не враховує загальний обсяг пам’яті, що використовується рядком, його індекси, первинні ключі та інші стовпці.

Як згадує ypercube у своєму коментарі, існують додаткові міркування щодо зберігання рядків у цілому, коли присутній хоча б один стовпчик, що зводить нанівець.

Фізична будова Innodb

Частина заголовка запису змінної довжини містить бітовий вектор для вказівки стовпців NULL. Якщо десь від 9 до 15 стовпців, які можуть бути NULL, бітовий вектор використовує два байти.)

...

Частина заголовка змінної довжини також містить довжини стовпців змінної довжини. Кожна довжина займає один або два байти, залежно від максимальної довжини стовпця. Якщо всі стовпці в індексі НЕ NULL і мають фіксовану довжину, заголовок запису не має частини змінної довжини

І так, використовуваний простір зберігання змінюється залежно від обраного типу, фіксований чи змінний, коефіцієнт порівняння та інші фактори, такі як двигун.

MySQL пропонує тут рекомендації щодо оптимізації зберігання даних: Оптимізація розміру даних

Оновлення

Один додатковий розгляд з varchar і це пам'ять. У MySQL важливо максимально обмежити розмір стовпця змінної довжини. Навіть незважаючи на те, що стовпець є змінним і використовуваний простір зберігання є змінним, MySQL виділить пам'ять у фіксованих фрагментах для зберігання значень. Наприклад, varchar (200) буде використовувати більше пам'яті, ніж varchar (5). Це не проблема місця для зберігання, але все-таки щось слід враховувати при визначенні своїх стовпців.


Цифри вище припускають CHARACTER SETlatin1 або ascii. Для utf8, необхідне місце для зберігання CHAR(4)- 12.
Рік Джеймс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.