Вплив на ефективність розмірів MySQL VARCHAR


45

Чи є різниця в продуктивності MySQL між розмірами varchar? Наприклад, varchar(25)і varchar(64000). Якщо ні, чи є причина, щоб не оголосити всі варшари з максимальним розміром лише для того, щоб у вас не було місця?


3
+1 це питання стосується всіх СУБД. Моє спостереження, як правило, зростає велика кількість варчарів.
bernd_k

5
Не MySQL, але ця публікація блогу від Depesz може відповісти на ваше запитання щодо PostgreSQL .
ксенотерацид

Відповіді:


29

Ви повинні усвідомити компроміси використання CHAR проти VARCHAR

З полями CHAR те, що ви виділяєте, саме те, що ви отримуєте. Наприклад, CHAR (15) виділяє і зберігає 15 байт, незалежно від того, як символи ви розміщуєте в полі. Маніпулювання рядками просте і просте, оскільки розмір поля даних повністю передбачуваний.

З полями VARCHAR ви отримуєте зовсім іншу історію. Наприклад, VARCHAR (15) насправді динамічно виділяє до 16 байт, до 15 для даних і, щонайменше, 1 додатковий байт для збереження довжини даних. Якщо у вас є рядок "привіт", який займе 6 байтів, а не 5. Маніпуляція з рядками завжди повинна виконувати певну форму перевірки довжини у всіх випадках.

Компроміс є більш очевидним, коли ви виконуєте дві речі:
1. Зберігання мільйонів чи мільярдів рядків
2. Індексація стовпців, що є або CHAR або VARCHAR

ТОРГОВОСТЬ №1

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

TRADEOFF №2

Оскільки поля CHAR потребують меншої маніпуляції з рядками через фіксовану ширину поля, пошук індексів щодо поля CHAR в середньому на 20% швидший, ніж для полів VARCHAR. Це не будь-яка здогадка з мого боку. Книга Дизайн та настройка баз даних MySQL виконала щось чудове на таблиці MyISAM, щоб довести це. Приклад у книзі зробив щось подібне:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Ця директива змушує VARCHAR поводитися як CHAR. Я зробив це на своїй попередній роботі ще в 2007 році і взяв таблицю на 300 ГБ і збільшив пошукові показники на 20%, не змінюючи нічого іншого. Це працювало як опубліковано. Однак вона створила таблицю майже вдвічі більше, але це просто повертається до компромісу №1.

Ви можете проаналізувати дані, що зберігаються, щоб побачити, що рекомендує MySQL для визначення стовпців. Просто запустіть наступне проти будь-якої таблиці:

SELECT * FROM tblname PROCEDURE ANALYSE();

Це дозволить пройти всю таблицю та рекомендувати визначення стовпців для кожного стовпця на основі даних, які він містить, мінімальних значень поля, максимальних значень поля тощо. Іноді просто потрібно використовувати здоровий глузд при плануванні CHAR vs VARCHAR. Ось хороший приклад:

Якщо ви зберігаєте IP-адреси, маска для такого стовпця має максимум 15 символів (xxx.xxx.xxx.xxx). Я б стрибнув прямо в CHAR (15) з серцебиттям, тому що довжина IP-адрес не зміниться настільки сильно, а додаткова складність маніпуляцій з рядками контролюється додатковим байтом. Ви все ще можете зробити ПРОЦЕДУРНИЙ АНАЛІЗ () проти такого стовпця. Може навіть рекомендувати VARCHAR. У цьому випадку мої гроші все одно будуть знаходитися на CHAR за VARCHAR.

Проблеми CHAR проти VARCHAR можна вирішити лише за допомогою належного планування. З великою силою приходить велика відповідальність (кліше, але правда)


4
Якщо ви зберігаєте IP-адреси, я не бачу причин зберігати їх як інше, ніж int. Це все IP-адреса. Багато мов мають якусь функцію ip2int. Якщо ви хочете домогтися виклику командного рядка, не важко скласти збережену процедуру для перетворення ABCD: A pow (256,3) + b pow (256,2) + c * 256 + d
atxdba

1
Помилка більше, я думаю, у mysql є своя функція ip2int: INET_ATON
atxdba

3
@atxdba: Суть моєї відповіді полягає лише у використанні CHAR vs VARCHAR. Я просто використовую IP як приклад, оскільки розмір його символу рядка ближче до 15. Таким чином, округлення стабільного розміру CHAR на користь VARCHAR - лише приклад заради самого питання. Ваш коментар щодо кращих способів представлення IP-адрес цілком справедливий і має найбільш сенс.
RolandoMySQLDBA

CHAR (15) виділяє 15 символів , а не байти . Для utf8, це 45 байт .
Рік Джеймс

2
Хоча це хороша відповідь щодо порівняння CHAR / VARCHAR, питання стосувалося різних розмірів VARCHAR.
Колекціонер

13

Відповідь на це насправді досить складна. Коротка версія: різниця є .

  1. Під час створення тимчасових таблиць для фільтрації результатів (наприклад, GROUP BYзаяви) буде розподілена повна довжина.

  2. Протокол проводів (відправлення рядків клієнту), швидше за все, виділяє більшу довжину.

  3. Двигун зберігання може / може не використовувати належну варшар.

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


Варто вказати. MySQL 5.7 може упакувати значення в буфер сортування (змінна довжина). Пояснюється більш докладно тут: mysqlserverteam.com/…
Morgan Tocker

9

Більшість відповідей у ​​цій темі мають 5 років, написані перед InnoDB та utf8 були за замовчуванням. Отже, дозвольте почати спочатку ...

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

  • TEXT/ BLOBстовпці, що витягуються, навіть TINYTEXT.
  • VARCHAR більша за якусь суму, ймовірно, 512 в поточній версії.

Також зауважте, що VARCHARsперетворюються на CHARs. Отже, VARCHAR(255)з CHARACTER SET utf8розширенням до 765 байт, незалежно від того, що знаходиться в стовпці. Потім це може бути спровоковано:

  • Якщо MEMORYтаблиця стає більшою за будь-яку max_heap_table_size або tmp_table_size , вона буде перетворена на MyISAM і, можливо, переллється на диск.

Отже, VARCHAR(25)швидше залишиться MEMORY, отже, швидше. (255)не так добре, а (64000)погано.

(В майбутньому, ймовірно, будуть тимчасові таблиці InnoDB, і частина цієї відповіді потребуватиме перегляду.)


6

Стовпець varchar такого розміру робить запити на всій таблиці більш імовірними для використання тимчасових таблиць. Відповідно до книги MySQL високої продуктивності. Коли оптимізатор намагається зрозуміти, чи може він виконувати цей запит у пам’яті чи йому потрібна тимчасова таблиця, він дивиться на розмір рядка на основі визначення таблиці, тобто для швидкості він не намагається побачити, скільки 64К символів ви фактично використовуєте. Ось чому письменники рекомендують не розтягувати цей спосіб визначення за межами реальних можливих значень, які йдуть у стовпці. Очевидно, що якщо ви налаштували більше запитів на тимчасові таблиці (навіть якщо фактичний розмір даних міг би вміститися в оперативній пам’яті), ви зараз зазнали штрафних санкцій за введення-виведення, яких ви могли уникнути.


Це дуже свіжа перспектива. Якщо це книга, на яку ви посилаєтесь ( amazon.com/MySQL-High-Available-Building-Centers/dp/… ), будь ласка, введіть у своїй відповіді номер сторінки книги, тому що я хотів би це прочитати. +1 !!!
RolandoMySQLDBA

Нерозумно мені… Висока ВИМОГА недоступність: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/…… номер сторінки 236/237 Це пояснює, як великодушність у визначенні стовпчика вархара може бути нерозумною. Майте на увазі, що ця книга була написана ще тоді, коли 5.1. Третє видання виходить в наступному році, щоб включити всі великі зміни в 5.5, так що, можливо, це зміниться :)
TechieGurl

Сторінка 236 згадує порівняння, що належать до певних наборів символів. Це може бути неприємно для VARCHAR. На сторінці 237 Параметри для зв'язку клієнт / сервер разом із малюнком 5-5 на сторінці 238 показують ще одну причину. Процес перекладу символів встановлюється вперед і назад. Знову ще одна неприємна пригода для VARCHAR.
RolandoMySQLDBA

Для уточнення, хоча цей розділ прямо не говорить про те, що MySQL піде на створення розміру, ми знаємо, що коли для операції потрібна тимчасова таблиця, ця таблиця знаходиться в MEMORY Engine і ТО завжди зберігає типи рядків у виправлення фрагментів, так що це щедрий Визначення може призвести до того, що потрібна таблиця тимчасових ПАМ’ЯТЬ перейде на диск на відміну від перебування в оперативній пам’яті
TechieGurl

@RolandoMySQLDBA. Так ... теж поєднання тут стає фактором (особливо якщо ви використовуєте UTF-8 і маєте не латинські символи), і все це просто вбиває вас, коли ви маєте справу з таблицею двигуна пам'яті і призводить до більш швидкої поїздки на диск
TechieGurl

5

Я розумію, що менші поля можуть бути включені в індекс безпосередньо, тоді як довші - не можуть. У зв'язку з цим обмеженням, якщо ви хочете, щоб рядки були індексуючими, я б сказав, щоб вони були коротшими. В іншому випадку, ні, будучи тим, як вони обидва варчара, тоді операції, такі як сортування чи порівняння, діятимуть за той самий час, будь то поля 25 чи MAX.


3

переконайтеся, що вам не вистачить місця

Ця фраза означає, що ви ставите питання, оскільки ви не впевнені в даних, які ви будете зберігати в базі даних. Якщо це правда, ви зможете дізнатися, як тільки зможете, тому що вам це знадобиться для планування потужностей. Якщо, можливо, ви отримуєте елементи даних із 7000 символами, наприклад, вам потрібно знати, оскільки це може мати наслідки для продуктивності для будь-якої СУБД.

При цьому я вважаю за краще розмір стовпців, пов'язаних із очікуваним вмістом. Наприклад, телефонний номер навряд чи буде довший 50 символів, навіть якщо ви включаєте код країни та розширення. Аналогічно, поштовий індекс або поштовий індекс, швидше за все, матиме 20 символів або менше.

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