NULL у MySQL (Продуктивність та зберігання)


77

Що саме робить null ефективністю та сховищем (простором) в MySQL?

Наприклад:

TINYINT: 1 байт TINYINT w / NULL 1 байт + якось зберігає NULL?

Відповіді:


103

Це залежить від того, який механізм зберігання даних ви використовуєте.

У форматі MyISAM кожен заголовок рядка містить бітове поле з одним бітом для кожного стовпця для кодування стану NULL. Стовпець із значенням NULL все ще займає місце, тому значення NULL не зменшує обсяг пам’яті. Див. Https://dev.mysql.com/doc/internals/en/myisam-introduction.html

У InnoDB кожен стовпець має "зміщення старту поля" в заголовку рядка, який становить один або два байти на стовпець. Високий біт у цьому полі зміщення старту ввімкнено, якщо стовпець NULL. У цьому випадку стовпець взагалі не потрібно зберігати. Отже, якщо у вас багато NULL, ваш обсяг пам’яті повинен бути значно зменшений. Див. Https://dev.mysql.com/doc/internals/en/innodb-field-contents.html

РЕДАГУВАТИ:

Біти NULL є частиною заголовків рядків, ви не вирішите їх додавати.

Єдиний спосіб, яким я можу уявити, що NULL покращує продуктивність, це те, що в InnoDB сторінка даних може вмістити більше рядків, якщо рядки містять NULL. Тож ваші буфери InnoDB можуть бути ефективнішими.

Але я був би дуже здивований, якщо це забезпечить значну перевагу на практиці. Турбуючись про вплив NULL на продуктивність, це в області мікро-оптимізації. Вам слід зосередити свою увагу в іншому місці, в областях, які дають більший виграш. Наприклад, додавання добре підібраних індексів або збільшення розподілу кешу бази даних.


Чи прискорить пошук NULL біт? (На відміну від просто залишення поля порожнім)
Стів

1
Дивіться додатковий вміст після "EDIT" у моєму коментарі вище.
Білл Карвін,

4
@Performance: Якщо у вас є індекс у стовпці, тобто NULL, MySQL потребує більше логіки для вибору, сортування тощо. Тому я рекомендую уникати NULL хоча б для індексованих полів з міркувань продуктивності.
Філ

@BillKarwin На офіційному сайті mysql згадують Not Null кращий за продуктивністю та розміром dev.mysql.com/doc/refman/5.5/en/data-size.html
Navrattan Yadav

@navy, я закликаю вас виконати деякі тести, щоб підтвердити, наскільки велика чи незначна різниця між використанням nulls чи не null.
Білл Карвін

40

Відповідь Білла хороша, але трохи застаріла. Використання одного або двох байтів для зберігання NULL стосується лише формату рядка InnoDB REDUNDANT. Оскільки MySQL 5.0.3 InnoDB використовує формат рядка COMPACT , який використовує лише один біт для зберігання NULL (звичайно, один байт є мінімальним), тому:

Необхідний простір для NULL = СТОЛ (N / 8) байт, де N - кількість стовпців NULL в рядку.

  • 0 NULLS = 0 байт
  • 1 - 8 НУЛЬ = 1 байт
  • 9-16 НУЛЬ = 2 байти
  • 17 - 24 НУЛІ = 3 байти
  • тощо ...

Згідно з офіційним сайтом MySQL про COMPACT проти REDUNDANT:

Компактний формат рядків зменшує простір для зберігання рядків приблизно на 20% за рахунок збільшення використання ЦП для деяких операцій. Якщо ваше робоче навантаження є типовим, обмеженим швидкістю потрапляння в кеш і швидкістю диска, компактний формат, швидше за все, буде швидшим.

Перевага використання NULLS над порожніми рядками або нулями:

  • 1 NULL вимагає 1 байт
  • 1 порожній рядок вимагає 1 байт (припускаючи VARCHAR)
  • 1 нуль вимагає 4 байтів (припускаючи INT)

Ви починаєте бачити економію тут:

  • 8 NULL вимагає 1 байт
  • 8 порожніх рядків вимагають 8 байт
  • 8 нулів вимагають 32 байти

З іншого боку, я пропоную використовувати NULL над порожніми рядками або нулями, оскільки вони більш організовані, портативні та вимагають менше місця. Щоб покращити продуктивність та заощадити простір, зосередьтеся на використанні належних типів даних, індексів та запитів замість дивних прийомів.

Докладніше на: https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html


отже, як я зрозумів з вашої відповіді, оптимізація закладена в Mysql? і я нічого не повинен робити, достатньо лише використання mysql 5.0.3 або вище?
Аммар Бозоргвар

@ ammar-bozorgvar Так, це робиться внутрішньо MySQL за замовчуванням при використанні InnoDB. Це офіційне посилання на документацію . Удачі!
Аріан Акоста

Я трохи заплутався: Білл сказав, що "Високий біт у цьому полі зміщення старту ввімкнено, якщо стовпець NULL. У такому випадку стовпець взагалі не потрібно зберігати", а ви сказали "8 NULL вимагає 1 байт ". Чи займають нулі місця чи ні? Подяка
bylijinnan

1
Тепер я розумію: 8 NULL вимагають 1 байт В ГОЛОВІ ЗАПИСУ, але NULL не зберігаються.
bylijinnan

6

Я погодився б із Біллом Карвіном, хоча додав би ці поради щодо MySQL . Номер 11 стосується саме цього:

Перш за все, запитайте себе, чи є якась різниця між значенням порожнього рядка та значенням NULL (для полів INT: 0 проти NULL). Якщо немає причин мати обидва, вам не потрібно поле NULL. (Чи знали ви, що Oracle вважає NULL і порожній рядок однаковими?)

Стовпці NULL вимагають додаткового простору, і вони можуть додати складності вашим операторам порівняння. Просто уникайте їх, коли можете. Однак я розумію, що у деяких людей можуть бути дуже конкретні причини мати значення NULL, що не завжди погано.

З іншого боку, я все ще використовую null для таблиць, які не мають тонн рядків, здебільшого тому, що мені подобається логіка сказати NOT NULL.

Оновлення Переглядаючи це пізніше, я б додав, що мені особисто не подобається використовувати в базі даних 0 замість NULL, і я не рекомендую цього Це може легко призвести до багатьох помилкових спрацьовувань у вашому додатку, якщо ви не будете обережні.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.