Важливість довжини варшара в таблиці MySQL


112

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


Таблиця з єдиним індексованим VARCHAR(255) utf8mb4стовпцем з ~ 150k рядків вимірювала 11,5 Мб. Таблиця з VARCHAR(48) utf8mb4індексованим стовпцем з тими ж даними (максимальна довжина 46 символів) використовувала 4,5 Мб. Не дуже велика різниця в запитах, вона індексується. Але він доповнює запити вводу-виводу та такі речі, як резервне копіювання бази даних.
Code4R7

Відповіді:


59

Ні, в тому сенсі, що якщо значення, які ви зберігаєте в цьому стовпці, завжди (скажімо) менше 50 символів, оголошуючи стовпець такою ж продуктивністю varchar(50)або varchar(200)має однакову продуктивність.


9
Не зовсім правда. Дивіться відповідь Білла Карвіна
хейдав

5
Я думаю, що відповідь на зразок повинна підтримуватися документами, орієнтирами чи чимось подібним.
Гохан Сарі

301

Існує один можливий вплив на продуктивність: у MySQL тимчасові таблиці та MEMORYтаблиці зберігають VARCHARстовпчик як стовпчик фіксованої довжини, підкреслений на максимальну довжину. Якщо ви проектуєте VARCHARстовпчики набагато більше, ніж потрібний вам найбільший розмір, ви будете витрачати більше пам'яті, ніж вам потрібно. Це впливає на ефективність кешу, швидкість сортування тощо.


33
+1. Мені здається, деякі драйвери JDBC, які виділяють достатньо місця для максимального розміру під час налаштування буферів для отримання рядків. Потрібно говорити, що це викликає сильний роздратування та скрегіт зубів, коли якийсь клоун щойно робив варчар (50000) на всякий випадок, якщо хтось має справді велике прізвище :-)
paxdiablo

21
+1. Це важливий вплив, і я вважаю, що це справжня відповідь на це питання.
Emre Yazici

6
Ця відповідь і прийнята відповідь необхідні для розуміння правильної відповіді на ОП.
kd8azz

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

1
Ця відповідь могла б визначити, для яких двигунів зберігання це правда (зауважу, що dev.mysql.com/doc/refman/8.0/en/… вказує на те, що тимчасові таблиці завжди є InnoDB, як у MySQL 8; чи щось змінить?) , а також із посиланнями на документи, які створюють резервну копію заявок, які вони пред'являють. З того, що я бачив з ваших результатів на Stack Exchange, я вірю, що ви мали рацію, коли ви це писали, але все, можливо, змінилося, і посилання стали б хорошим прикладом для інших і допоможуть навчити решту нас шукати такого роду інформація для себе.
Марк Амері

14

VARCHAR ідеально підходить для ситуації, яку ви описуєте, оскільки вона означає "змінний символ" - обмеження, засноване на вашому прикладі, буде 200 символів, але все менше приймається і не заповнить виділений розмір стовпця.

VARCHAR також займає менше місця - значення зберігаються у вигляді однобайтової або двобайтової префікса плюс дані. Префікс довжини вказує кількість байтів у значенні. У стовпці використовується один байт довжини, якщо для значень потрібно не більше 255 байт, два байти довжини, якщо значення може вимагати більше 255 байт.

Для отримання додаткової інформації про порівняння даних MySQL CHAR з типами даних VARCHAR див. Це посилання .


1
всі, хто цікавиться у сховищі MySQL (про CHAR та VARCHAR), повинні прочитати посилання, згадане у цій відповіді. Дякую!
Паскаль

14

Розмір - продуктивність! Чим менше розмір, тим краще. Не сьогодні чи завтра, але в якийсь день ваші столи виростуть до розміру, коли мова йде про серйозні вузькі місця, незалежно від того, який дизайн ви виклали. Але ви можете передбачити деякі з тих потенційних вузьких місць у вашій фазі проектування, які, ймовірно, відбудуться першими, і спробувати збільшити час, коли ваш db буде працювати швидко і щасливо, поки вам не потрібно переосмислити схему або масштабувати горизонтально, додавши більше серверів.

У вашому випадку існує багато витоків продуктивності, з якими ви можете зіткнутися: великі об'єднання майже неможливі з довгими varcharстовпцями. Індексація в цих стовпцях - справжній вбивця. Ваш диск повинен зберігати дані. Одна сторінка пам’яті може містити менше рядків, а сканування таблиці буде набагато повільніше. Також кеш запитів навряд чи допоможе вам тут.

Ви повинні запитати себе: скільки вкладок на рік може трапитися? Яка середня довжина? Мені справді потрібно більше 200 символів чи я можу це зрозуміти в моєму додатку, навіть повідомляючи користувачів про максимальну довжину? Чи можна розділити таблицю на вузьку для швидкого індексування та сканування та іншу для зберігання додаткових, рідше потрібних даних, що розширюються? Чи можу я ввести можливі дані varchar у категорії і таким чином витягнути деякі дані в кілька менших, можливо, int або bool-типів, і таким чином звузити стовпчик varchar?

Тут можна багато зробити. Можливо, найкраще спершу припустити, а потім переробити крок за кроком, використовуючи дані про продуктивність, виміряні в реальному житті. Удачі.


+1 для перерахування варіантів дизайну та вивчення впливу. Дуже корисно і для мого питання. stackoverflow.com/q/12083089/181638
Асад Ебрагім

5
Чи є якийсь фактичний вплив на продуктивність від встановлення великої максимальної довжини, або продуктивність визначається фактично розміром?
poolie

5

Продуктивність? Ні. Дисковий накопичувач? Так, але це дешево і рясно. Якщо ваша база даних не виросте до терабайтної шкали, ви, мабуть, добре.


Як не дивно, що ця відповідь була оскаржена через шість років після її опублікування, і ніхто з інших не був. Здається помстивим і дріб'язковим. У цій відповіді немає нічого неправильного. Модератори?
duffymo

1
Як було сказано, це впливає на продуктивність. Також дискове зберігання також не є безкоштовним. Більш широкий стовпець означає більше читання / запису диска (а доступ до диска - slooooooow), а також більш широкі індекси, що зменшує їх корисність. Обидві речі негативно впливають на ефективність роботи. Можливо, це незначно в невеликій базі даних, але в масштабі гігабайт / терабайт це, безумовно, має значення. Для таблиці 100 реєстрації це не має значення.
Алехандро

5

Деякі з вас помиляються, думаючи, що varchar(200)розмір таблиці займає більше диска, ніж а varchar(20). Це не так. Тільки коли ви виходите за рамки 255 символів, mysql використовує додатковий байт, щоб визначити довжину varcharпольових даних.


9
Не так для тимчасових таблиць і MEMORYтаблиць.
Гонки легкості по орбіті

4
Щоразу, коли ваш запит вибору використовує тимчасову таблицю (групування та впорядкування за операціями, серед іншого), він перетворить varchar (200) у char (200), а продуктивність постраждає.
Джеймі

1

Тут можуть бути хіти для продуктивності, але зазвичай це не на рівні, який помітить більшість користувачів.

Коли розмір кожного поля відомий заздалегідь, MySQL точно знає, скільки байтів знаходиться між кожним полем / рядком і може переходити на сторінку вперед, не читаючи всіх даних. Використання змінних символів зменшує цю здатність для оптимізації.

Чи призводить до того, що варчар призводить до ефективності завдяки фрагментації даних?

Ще краще, char vs varchar .

Для більшості застосувань ви будете добре з будь-яким - але є різниця, і для великих масштабних баз даних є причини, чому ви обираєте ту чи іншу.


0

Будучи вархаром, а не просто char, розмір базується на внутрішньому полі, щоб вказати його фактичну довжину та саму рядок. Тож використання varchar (200) не сильно відрізняється від використання varchar (150), за винятком того, що у вас є потенціал зберігати більше.

І вам слід врахувати, що відбувається під час оновлення, коли рядок зростає. Але якщо це трапляється рідко, то вам слід добре.


0

згідно з назвою типу даних випливає, що це VARCHAR, тобто зберігання даних змінних символів, двигун mysql сам виділяє використовувану пам'ять відповідно до збережених даних, тому за моїми знаннями не буде досягнуто жодної ефективності.


0

Ви повинні спробувати переглянути колонку varchar такою ж, як і у стовпці char, у більшості сценаріїв і встановити довжину консервативно. Вам не потрібно завжди думати про модифікатор var настільки, як на щось, що впливає на прийняття рішення на максимальну довжину. Це дійсно слід розглядати як натяк на ефективність, а не те, що надані рядки будуть різної довжини.

Це не директива, якої слід суворо дотримуватися внутрішніми базами даних, її можна повністю ігнорувати. Але будьте обережні з цим, оскільки іноді реалізація може просочитися (наприклад, фіксованою довжиною і накладкою), хоча це не повинно бути в ідеальному світі.

Якщо у вас варчар (255), то ви не маєте гарантії, що ефективність роботи завжди буде поводитися по-різному зі статусом (255) за будь-яких обставин.

Це може здатися просто встановити на щось таке, як 255, 65535, тощо, відповідно до порад, наданих у посібнику щодо вимог щодо зберігання. Це створює враження, що будь-яке значення між 0 (так, це річ) і 255 матиме однаковий вплив. Однак це не те, що можна повністю гарантувати.

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

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

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

Набір символів також слід враховувати, де тривалість і продуктивність вступають у гру. Довжина стосується цього, а не байтів. Якщо, наприклад, використовується utf8 (не MB4), то varchar (255) справді є варбінарним (3 * 255). Важко знати, як подібні речі справді розігруватимуться без запуску тестів та глибокого погляду на вихідний код / ​​документацію. Через це існує можливість, щоб надмірна довжина мала несподівано завищений вплив. це не стосується лише продуктивності. Якщо вам одного дня потрібно змінити набір символів стовпчика варшара на більший, ви можете в кінцевому підсумку досягти деякої межі без регресу, якщо ви дозволили б присутні безперечно довгі рядки, яких можна було б уникнути. Зазвичай це досить ніша проблема, але вона виникає,

Якщо виявиться, що MAX (LENGTH (стовпець)) завжди <64 (наприклад, якби було вирішено, що буде обмеження на вхід, який не відповідає визначенню стовпця), але у вас є varchar (255), то є хороший шанс, що ви будете використовувати в чотири рази більше місця, ніж потрібно в деяких сценаріях.

Це може включати:

  • Різні двигуни, деякі можуть взагалі проігнорувати це.
  • Розміри буфера, наприклад, оновлення або вставки, можливо, доведеться виділити цілі 255 (хоча я не перевіряв вихідний код, щоб довести це, це лише гіпотетична).
  • Покажчики, це стане очевидним, якщо ви спробуєте скласти складний ключ із безлічі вархарських (255) стовпців.
  • Проміжні таблиці та, можливо, набори результатів. Враховуючи спосіб роботи транзакцій, можливо, не завжди можливо щось використовувати фактичну максимальну довжину рядків у стовпці на відміну від визначеної межі.
  • Внутрішні оптимізації прогнозування можуть сприймати максимальну довжину як вхід.
  • Зміни у версіях реалізації бази даних

Як правило, дійсно не потрібно, щоб варчар був довшим, ніж це повинно бути в будь-якому випадку, питання щодо продуктивності чи ні, тому я рекомендую дотримуватися цього, коли можете. Доклавши більше зусиль для вибірки розміру ваших даних, застосуйте істинний ліміт або з’ясувати справжню межу шляхом запитання / дослідження - це ідеальний підхід.

Коли ви не можете, якщо ви хочете зробити щось на зразок varchar (255) для випадків, коли сумніваєтесь, то рекомендую займатися наукою. Це може складатися з дублювання таблиці, зменшення розміру стовпця var char, а потім копіювання даних у неї з оригіналу та перегляду розміру даних індексу / рядка (також індексуйте стовпець, а також спробуйте це як первинний ключ, який може поводитися по-різному в InnoDB, оскільки рядки впорядковані первинним ключем). По крайней мере, таким чином ви дізнаєтесь, чи маєте ви вплив на IO, який, як правило, є одним з найбільш чутливих вузьких місць. Тестування на використання пам'яті складніше, важко перевірити це вичерпно. Я рекомендую протестувати потенційні найгірші випадки (запити з великою кількістю проміжних результатів у пам'яті, перевірити з поясненням щодо великих темп-таблиць тощо).

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

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