Відповіді:
Це дуже поширене "питання на іспит / співбесіду". Я відповім як можна краще:
У стандартних форматах рядків для InnoDB та MyISAM (динамічний / компактний) a VARCHAR(50)
та a VARCHAR(255)
зберігатимуть текст рядка таким же чином - 1 байт на довжину та фактичний рядок від 1 до 4 байт на символ (залежно від кодування та фактичний символ зберігається).
Насправді, якщо я добре пам’ятаю, я згадую, що хтось модифікував словник даних з шістнадцятковим редактором, щоб змінити щось на зразок a VARCHAR(50)
на a VARCHAR(100)
, щоб це могло бути зроблено динамічно (як правило, це потребує реконструкції таблиці). І це було можливо, оскільки фактичні дані не вплинули на цю зміну.
Це не вірно VARCHAR(256)
, тому що тоді завжди потрібно 2 байти (принаймні) для довжини.
Отже, це означає, що ми завжди повинні робити VARCHAR(255)
, чи не так? Ні. Є кілька причин.
Хоча InnoDB може зберігати варчар динамічно, це не стосується інших двигунів. MyISAM має фіксований формат розміру рядків, і таблиці MEMORY завжди фіксуються за розміром. Чи варто дбати про ці інші двигуни? Так, ми повинні, тому що навіть якщо ми не використовуємо їх безпосередньо, таблиці ПАМ’ЯТЬ дуже часто використовуються для проміжних результатів (тимчасові таблиці на пам'яті) , і оскільки результати заздалегідь не відомі, таблицю потрібно створити з максимальним розміром можливо - VARCHAR(255)
якщо це наш тип. Якщо ви можете подумати про витрачений простір, якщо ми використовуємо 'utf8' charset
кодування MySQL , MEMORY резервує 2 байти на довжину + 3 * 255 байт у рядку(для значень, які на InnoDB можуть займати лише кілька байт). Це майже 1 Гб на столиці на 1 мільйон - тільки для VARCHAR. Це не тільки спричиняє непотрібне напруження пам’яті, це може спровокувати дії, що виконуються на диску, потенційно уповільнюючи його тисячі разів. Все це через поганий вибір визначеного типу даних (незалежно від вмісту).
Це має певні наслідки і для InnoDB. Розмір індексу обмежений 3072 байтами та індексами одного стовпця, до 767 байт *. Отже, дуже ймовірно, що ви не зможете повністю проіндексуватиVARCHAR(255)
поле (якщо припустимо, що ви використовуєте utf8 або будь-яке інше кодування змінної довжини).
Крім того, максимальний розмір рядка вбудованого рядка для InnoDB становить півсторінки (близько 8000 байт), а поля зі змінною довжиною, такі як BLOB або varchar, можуть зберігатися поза сторінкою, якщо вони не вміщуються на половині сторінки . Це має певні наслідки в продуктивності (іноді хороші, іноді погані, залежно від використання), які не можна ігнорувати. Це спричинило деякі дивацтва між форматами COMPACT та DYNAMIC. Дивіться, наприклад: помилка 1118: розмір рядка занадто великий. utf8 innodb
І останнє, але не менш важливе, як нагадав мені @ypercube, для довжини може знадобитися більше 1 байти, навіть якщо ви використовуєте VARCHAR(255)
, оскільки визначення є символами, тоді як довжина зберігає байти. Наприклад REPEAT('ñ', 255)
, більше 2 ^ 255 байт у utf8, тому для зберігання його довжини знадобиться більше 1 байти:
mysql> SELECT LENGTH(REPEAT('ñ', 255));
+---------------------------+
| LENGTH(REPEAT('ñ', 255)) |
+---------------------------+
| 510 |
+---------------------------+
1 row in set (0.02 sec)
mysql> SELECT CHAR_LENGTH(REPEAT('ñ', 255));
+--------------------------------+
| CHAR_LENGTH(REPEAT('ñ', 255)) |
+--------------------------------+
| 255 |
+--------------------------------+
1 row in set (0.00 sec)
Таким чином, загальна порада полягає у використанні найменшого можливого типу , оскільки це може потенційно створити проблеми з ефективністю чи управлінням в іншому випадку. А VARCHAR(100)
краще, ніж VARCHAR(255)
(хоча а VARCHAR(20)
було б краще), навіть якщо ви не знаєте точної довжини. Постарайтеся бути консервативними, оскільки, якщо таблиця не надто велика, ви завжди можете змінити визначення пізніше.
Оновлення: Оскільки зростаюча популярність струн змінної довжини, наприклад, за допомогою емоджи, Oracle домагається підвищення продуктивності для цих випадків. В останніх версіях MySQL (5.6, 5.7) InnoDB був встановлений як двигун за замовчуванням як для внутрішніх, так і явних тимчасових таблиць, тобто поля змінної довжини тепер є першокласними громадянами. Це означає, що може бути менше причин мати дуже обмежену довжину символів (але вони все ще існують).
(*) Друге оновлення : великий_prefix_index тепер увімкнено за замовчуванням на останніх версіях MySQL (8.0), але це все ще справедливо для старих версій або якщо ви використовуєте старі формати файлів / рядків innodb (крім динамічного чи стисненого), але тепер за замовчуванням індекси одного стовпця можуть бути до 3072 байтів.
Забудьте про префікс 1- проти 2-байт на VARCHARs
.
На питання про 255 вже багато разів задавали і відповідали.
VARCHARs
може призвести до збою CREATE TABLE
.MEMORY
таблиці, з VARCHARs
перетвореними на VARCHAR
. Це означає, наприклад, що VARCHAR(255) CHARACTER SET utf8mb4
потрібно фіксовану довжину 1020 байт. (Це не вдасться, і це перетвориться на використання MyISAM.)Підсумок: не використовуйте сліпо 255 (або 256); робити те, що має сенс для схеми.