Существуют ли недостатки в использовании общего varchar (255) для всех текстовых полей?

У меня есть таблица contacts, которая содержит такие поля, как postcode, first name, last name, town, country, phone number и т.д., все из которых определены как VARCHAR(255) хотя ни одно из этих полей никогда не приблизится к 255 символам. (Если вам интересно, это так, потому что Ruby on Rails migrations сопоставляет строковые поля по VARCHAR(255) по умолчанию, и я никогда не удосужился переопределить его).

Так как VARCHAR будет хранить только количество фактических символов поля (вместе с длиной поля), есть ли какое-либо преимущество (производительность или иное) на использование, скажем, VARCHAR(16) над VARCHAR(255)?

Кроме того, большинство из этих полей имеют индексы. Чем больше размер VARCHAR в поле влияет на размер или производительность индекса?

FYI Я использую MySQL 5.

Ответ 1

В хранилище VARCHAR(255) достаточно умен, чтобы хранить только нужную длину в данной строке, в отличие от CHAR(255), которая всегда хранит 255 символов.

Но поскольку вы отметили этот вопрос в MySQL, я упомянул советник, специфичный для MySQL: поскольку строки копируются с уровня ядра хранилища на уровень SQL, поля VARCHAR преобразуются в CHAR, чтобы получить преимущество работы с строками фиксированной ширины. Таким образом, строки в памяти становятся заполнены до максимальной длины вашего объявленного столбца VARCHAR.

Когда ваш запрос неявно генерирует временную таблицу, например, при сортировке или GROUP BY, это может использовать много памяти. Если вы используете много полей VARCHAR(255) для данных, которые не должны быть такими длинными, это может сделать временную таблицу очень большой.

Вам также может понравиться знать, что это поведение "padding out" означает, что строка, объявленная с набором символов utf8, заполняет три байта на символ даже для строк, которые вы храните с однобайтовым контентом (например, ascii или latin1), И аналогичный набор символов utf8mb4 заставляет строку выкладывать до четырех байтов на символ в памяти.

Итак, VARCHAR(255) в utf8, хранящем короткую строку, такую ​​как "No opinion", принимает 11 байтов на диске (десять символов нижнего символа плюс один байт для длины), но он занимает 765 байт в памяти и, следовательно, в временных таблицах или отсортированные результаты.

Я помог пользователям MySQL, которые неосознанно создали временные таблицы на 1,5 ГБ и заполнили их дисковое пространство. У них было много столбцов VARCHAR(255), которые на практике сохраняли очень короткие строки.

Лучше всего определить столбец на основе типа данных, которые вы собираетесь хранить. Как и другие люди, он имеет преимущества для обеспечения ограничений, связанных с приложениями. Но он имеет физические преимущества, чтобы избежать отходов памяти, которые я описал выше.

Трудно понять, что такое самый длинный почтовый адрес, поэтому многие люди выбирают длинный VARCHAR, который, безусловно, длиннее любого адреса. И 255 является обычным, поскольку это максимальная длина VARCHAR, длина которой может быть закодирована с помощью одного байта. Это также максимальная длина VARCHAR в MySQL старше 5.0.

Ответ 2

В дополнение к соображениям размера и производительности при настройке размера varchar (и, возможно, более важно, поскольку хранение и обработка становятся все дешевле каждую секунду), недостаток использования varchar (255) "только потому, что" - это сокращение целостности данных.

Определение максимальных пределов для строк - это хорошая вещь, чтобы сделать, чтобы предотвратить более длинные, чем ожидаемые строки, вход в RDBMS и последующее переполнение буфера или исключения/ошибки при извлечении и анализе значений из базы данных, которые дольше (больше байтов), чем ожидалось.

Например, если у вас есть поле, которое принимает двухсимвольные строки для сокращений по странам, то у вас нет мыслимой причины ожидать, что ваши пользователи (в этом контексте, программисты) будут вводить полные названия стран. Поскольку вы не хотите, чтобы они входили в "Антигуа и Барбуду" (AG) или "Остров Херда и острова Макдональд" (HM), вы не разрешаете его на уровне базы данных. Кроме того, вероятно, некоторые программисты еще не создали RTFMed конструкторскую документацию (которая, безусловно, существует), чтобы не знать этого.

Задайте поле для приема двух символов и пусть RDBMS справится с ним (либо изящно, усекаясь, либо безжалостно, отклоняя их SQL с ошибкой).

Примеры реальных данных, которые не имеют причины превышать определенную длину:

  • Канадские почтовые коды имеют формат A1A1A1 и всегда имеют 6 символов, даже для Санта-Клауса (6 символов исключают пространство, которое может указывается для удобочитаемости).
  • адреса электронной почты - до 64 байт до @, до 255 байт. Никогда больше, чтобы вы не нарушили Интернет.
  • Номера телефонов в Северной Америке не более 10 цифр (без кода страны).
  • Компьютеры, работающие (последние версии) Windows не могут иметь имена компьютеров длиной более 63 байтов, хотя более 15 не рекомендуется и будет разорвать ваш Ферма серверов Windows NT.
  • Аббревиатуры состояний - 2 символа (например, коды стран, рассмотренных выше).
  • Номера отслеживания UPS - 18-, 12-, 11- или 9-значные. 18-символьные номера начинаются с "1Z", а 11-символьные номера начинаются с "T", что заставляет вас задаться вопросом, как они доставляют все эти пакеты, если они не знают разницы между буквами и цифрами.

И так далее...

Потратьте время на размышления о своих данных и его ограничениях. Если вы архитектор, разработчик или программист, это ваша работа, в конце концов.

Используя varchar (n) вместо varchar (255), вы устраняете проблему, когда пользователи (конечные пользователи, программисты и другие программы) вводят неожиданно длинные данные, которые возвращаются, чтобы преследовать ваш код позже.

И я не сказал, что вы также не должны применять это ограничение в коде бизнес-логики, используемом вашим приложением.

Ответ 3

Я с тобой. Чрезмерное внимание к деталям - боль в шее и имеет ограниченную ценность.

Когда-то диск был драгоценным товаром, и мы использовали пот пуль для его оптимизации. Цена хранения упала в 1000 раз, что сократило время, затрачиваемое на сжатие каждого байта.

Если вы используете только поля CHAR, вы можете получить строки фиксированной длины. Это может сэкономить некоторый резервный диск, если вы выбрали точные размеры полей. Вы можете получить более плотно упакованные данные (меньше ввода-вывода для сканирования таблиц) и более быстрые обновления (проще найти открытые пространства в блоке для обновлений и вставок.)

Однако, если вы переоцените свои размеры или ваши фактические данные будут переменными, вы потеряете пространство с полями CHAR. Данные будут менее плотно упакованы (что приведет к большему количеству операций ввода-вывода для больших поисков).

Как правило, преимущества производительности при попытке поместить размер в поля переменных незначительны. Вы можете легко сравнивать, используя VARCHAR (255) по сравнению с CHAR (x), чтобы определить, можете ли вы измерить разницу.

Однако иногда мне нужно предоставить "маленький", "средний", "большой" намек. Поэтому я использую 16, 64 и 255 для размеров.

Ответ 4

В настоящее время я не могу себе представить, что это действительно имеет значение.

Там есть вычислительные накладные расходы на использование полей переменной длины, но с избытком процессоров сегодня, это даже не стоит рассматривать. Система ввода-вывода настолько медленна, что любые вычислительные затраты для обработки varchars фактически несуществуют. Фактически, цена вычислительной машины varchar, вероятно, является чистой победой над объемом дискового пространства, сохраненного с использованием полей переменной длины по полям фиксированной длины. Вы, скорее всего, имеете большую плотность строк.

Теперь сложность полей varchar заключается в том, что вы не можете легко найти запись через нее номер записи. Когда у вас есть размер строки фиксированной длины (с полями фиксированной длины), тривиально вычислять блок диска, на который указывает идентификатор строки. С переменным размером rowize этот вид выходит из окна.

Итак, теперь вам нужно поддерживать какой-то индекс номера записи, как и любой другой первичный ключ, ИЛИ вам нужно создать надежный идентификатор строки, который кодирует детали (например, блок и т.д.) в идентификатор. Однако, если вы это сделаете, идентификатор должен быть пересчитан, если строка будет перемещена на постоянное хранилище. Не важно, просто нужно переписать все записи в индексе и убедиться, что вы либо a) никогда не подвергаете его потребителю, либо б) никогда не утверждаете, что число надежное.

Но так как у нас есть поля varchar сегодня, единственное значение varchar (16) над varchar (255) заключается в том, что БД будет применять предел 16 char на varchar (16). Если предполагается, что модель БД действительно представляет собой модель физических данных, то длина полей может быть полезной. Если, однако, это просто "хранилище", а не "модель И хранилище", нет никакой необходимости.

Затем вам просто нужно различать текстовое поле, которое является индексируемым (такое varchar), что-то, что не является (как текстовое поле или поле CLOB). Индексируемые поля, как правило, имеют ограничение по размеру для облегчения индекса, тогда как поля CLOB не являются (в пределах разумного).

Ответ 5

По моему опыту, если вы разрешите тип данных из 255 символов, какой-то глупый пользователь (или какой-то опытный тестер) на самом деле заполнит это.

Тогда у вас есть всевозможные проблемы, в том числе сколько места вы позволяете этим полям в отчетах и ​​экранных дисплеях в своем приложении. Не говоря уже о возможности превышения предела строки для данных в вашей базе данных (если у вас было несколько таких 255 полей символов).

Намного легче выбрать разумный предел в начале, а затем применить это через приложение и базу данных.

Ответ 6

Хорошая практика состоит в том, чтобы выделить немного меньше того, что вам нужно. Телефонные номера никогда не будут такими большими.

Одна из причин заключается в том, что, если вы не проверите против больших записей, несомненно, кто-то будет использовать все, что есть. Тогда в вашей строке может появиться пробел. Я не уверен в ограничении MySQL, но 8060 - это максимальное количество строк в MS SQL.

Более нормальное значение по умолчанию будет 50 imho, а затем увеличится, когда это докажет его.

Ответ 7

В контексте mysql он может стать важным при работе с индексами в указанных столбцах varchar, поскольку mysql имеет макс. предел 767 байт за строку индекса.

Это означает, что при добавлении индекса по нескольким столбцам varchar 255 вы можете быстро достичь этого/даже быстрее на utf8 или utf8mb4, как указано в ответах выше.