2009-08-11 6 views
18

В slightly heated discussion on TDWTF возник вопрос о размере столбцов varchar в БД.Какой размер выбрать для столбца (n) varchar?

Например, возьмите поле, содержащее имя человека (только имя, фамилию). Легко видеть, что это будет не очень долго. У большинства людей есть имена с менее чем 10 символами, и немногие из них выше 20. Если вы сделаете свой столбец, скажем, varchar (50), он определенно будет содержать все имена, с которыми вы когда-либо сталкивались.

Однако для большинства СУБД не имеет значения размер или скорость, независимо от того, сделаете ли вы varchar (50) или varchar (255).

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


Добавлено: Люди хотят ссылки на заявления о «нет никакой разницы в размерах и скорости». ОК. Вот они:

Для MSSQL: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Размер хранения фактическая длина введенных данных + 2 байта.

Для MySQL: http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

L + 1 байт, если значения столбцов требуют 0 - 255 байт, L + 2 байта, если значения может потребоваться более 255 байт

не могу найти документацию для Oracle, и я не работал с другими СУБД. Но у меня нет оснований полагать, что там что-то другое.

+1

Мне понравится ссылка на «Однако для большинства СУБД не имеет никакого значения в размере или скорости, независимо от того, делаете ли вы varchar (50) или varchar (255) » –

+0

См. Http://stackoverflow.com/questions/177354/size-of-varchar-columns –

+1

Это не дубликат - это более общий вопрос, а не только о MSSQL. –

ответ

19

Я могу говорить только о Oracle. VARCHAR2 (50) и VARCHAR2 (255) занимают ровно столько же места и выполняют тождественно, если вы вводите значение «SMITH».

Тем не менее, причина, по которой вообще не рекомендуется обсуждать все ваши текстовые столбцы, поскольку VARCHAR2 (4000) - это то, что длина столбца является, фактически, еще одним ограничением. И ограничения - это реализация бизнес-правил в базе данных, поэтому они определенно должны быть определены на стороне базы данных.

В качестве примера. Вы определяете ограничение CHECK для столбца, чтобы значения, которые он может принимать, являются только «Y» и «N». Это избавляет ваше приложение от необходимости иметь дело с «y» и «n» или даже «1» и «0». Ограничение проверки гарантирует соответствие ваших данных ожидаемым стандартам. Затем ваш код приложения может сделать допустимые предположения о характере данных, с которыми он должен иметь дело.

Определение длины столбца находится в одной лодке. Вы заявляете что-то вроде VARCHAR2 (10), потому что вы не хотите, чтобы он принимал запись «ABC123ZYX456» (по какой-либо причине!)

В Австралии я определяю столбцы STATE как varchar2 (3), потому что я не хотят, чтобы люди печатали «Новый Южный Уэльс» или «Южную Австралию». Определение столбца в значительной степени заставляет их вводиться как «NSW» и «SA».В этом смысле VARCHAR2 (3) является почти таким же контрольным ограничением, как и фактическое указание ограничения CHECK IN ('NSW', 'SA', 'VIC' и т. Д.).

Короче говоря, правильные длины столбцов являются способом кодирования бизнес-правил. Это еще одна форма ограничения. Они приносят все преимущества ограничений (и страдают от многих из тех же недостатков). И они в малой степени обеспечивают степень «чистоты данных», с которой также помогают «правильные» ограничения.

Я также не покупаю аргумент, что лучше всего придерживаться такого рода вещей в клиентском приложении, потому что там легче изменить его. У вас 20 000 человек, использующих приложение, это 20 000 обновлений. У вас есть одна база данных, это одно обновление. Аргумент «проще изменить клиентское приложение», если это правда, потенциально может означать, что база данных просто рассматривается как гигантское ведро бит, причем всякая умная логика обрабатывается в клиентском коде. Это большая дискуссия, но поскольку все RDBMS позволяют определять ограничения и т. Д. В самой базе данных, довольно ясно, что существует, по крайней мере, целесообразный случай, когда такая фундаментальная логика принадлежит бэкенду.

+7

Это хороший ответ, но он просто приводит к другому вопросу: так что же тогда разумное ограничение длины для имени? и есть ли даже один? –

+1

Приобретено за хорошее, подробное обсуждение! :) Тем не менее, я ничего не сказал в своем OP. Да, бывают случаи, когда имеет смысл поставить ограничение на строку. Как хэш пароля или «трехбуквенный код состояния». Но в подавляющем большинстве случаев поля varchar предназначены для имен и описаний, где нет очевидного предела. –

+1

Хотя я согласен с тем, что это * другое ограничение, оно не заменяет * других * ограничений. Например. принятие '42!' для столбца STATE [вероятно] недействительно, даже если оно всего 3 символа. – 2012-03-01 22:59:55

3

Итак, почему люди пытаются сделать свои столбцы как можно меньше? Я не верю, что сделаю их настолько маленькими, насколько это возможно, но соответствующим образом определяя их. Некоторые причины для создания (n) varchars меньше, чем больше:

1) С большим полем все клиенты, которые используют базу данных, должны иметь возможность обрабатывать полный размер. Возьмем, например, систему, которая содержит адрес Соединенных Штатов с 255 символов в каждом поле: (. Подобно TDWTF что вы ссылаетесь, я считаю)

  • Имя
  • Фамилия
  • Строка адреса 1
  • Строка адреса 2
  • Город
  • государственный
  • индекс

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

Но мне не хотелось бы проблемы с форматированием адреса для конверта, который может содержать 255 символов для каждого из этих полей или только для любого из этих полей. Собираетесь ли вы усечь, если поле слишком длинное, чтобы соответствовать? У большого кого-то есть Адресная линия 1 «Номер дома Номер Стойки ... бла-бла-бла ... Номер квартиры 111.» И вы удалите важный номер квартиры. Вы собираетесь обернуть? Сколько? Что делать, если вы просто не можете поместить его в маленькую коробку пространства на конверте? Поднимите исключение и попросите кого-нибудь передать письмо?

2) В то время как 10 символов данных, хранящихся в varchar (50) по сравнению с varchar (255), не влияют на размер или скорость, позволяя использовать 255 символов для большего пространства. И если все поля такие большие, вы можете столкнуться с ограничениями по размеру в SQL Server 2000. (Я не читал в 2005 году & 2008, чтобы узнать, могут ли они обрабатывать строки, превышающие одну страницу.) И с Oracle вы больше размеров допускаете строку цепочка произойдет, если кто-то фактически использует все доступные символы.

3) Индексы имеют более строгие ограничения по размеру, чем листовые страницы. Вы можете исключить индексы, особенно составные индексы, если вы создаете свои varchars слишком большими.


С другой стороны, у меня есть длинная строка 1 для моего адреса, и были разочарованы веб-сайты, которые не позволяют в полной мере, что нужно быть набраны.

+7

1) Если есть на самом деле это ограничение по размеру (например, доступное пространство на конверте), тогда имеет смысл поставить предел там, который я уже заметил в своем вопросе. Но я предпочел бы сделать предел в своем клиентском приложении, чем в БД. Поскольку, если предел когда-либо изменился, мне пришлось бы только изменить клиентское приложение - в большинстве случаев задача намного проще, чем обновление базы данных БД. –

+1

2) Размер строки - это точка, однако, поскольку большинство реальных данных не достигнут этих пределов, маловероятно, что ряд будет таким большим. Большие размеры означают больше для отказоустойчивости, чем фактическое использование. –

+0

3) Еще один момент - но мои мысли такие же, как в 2). –

5

Я слышал, что оптимизатор запросов делает Учитывать длину varchar, хотя я не могу найти ссылку.

Определение длины varchar помогает сообщить о намерениях. Чем больше ограничений определено, тем надежнее данные.

+3

Я согласен с намерением, но я не вижу, как это сделает данные более надежными. –

+0

Я должен был сказать «предсказуемый», а не надежный. Чем меньше значений может иметь переменная, тем меньше шансов сделать что-то, чего я не ожидаю. –

+1

Если вы не программируете на C/C++ или другом языке, где вам нужно беспокоиться о переполнении буфера, одна строка будет такой же, как и другая в вашем коде. –

1

Я отвечу на ваш вопрос вопросом: если нет разницы между СУБД между varchar (50) и varchar (255), почему СУБД позволит вам сделать различие? Почему бы СУБД просто не сказать «использовать varchar для символов до xxx, а также текст/clob/и т. Д. Для чего-либо над этим». Несомненно, возможно, Microsoft/Oracle/IBM может содержать определение длины по историческим причинам, но как насчет СУБД, например MySQL, который имеет несколько серверов хранения данных - почему каждый из них реализует определяемые длины столбцов символов?

+0

Потому что иногда вам нужно ограничение длины? Хотя тогда это было бы лучше, чем параметр/constraint/not a column datatype. Хорошо, я не знаю. :) –

+0

Право. Поэтому в стороне от обратной совместимости нет причины «на первый взгляд» для существования такой функции. Это говорит о том, что у него есть глубокая причина. Я полагаю, возможно, что другие СУБД «сделают это по-моему», но я полагаю, что разработчики не добавляют функции ради добавления функций. По крайней мере, я этого не делаю :) – Dan

+4

Или, может быть, это историческая функция, которая приходит с 80-х годов, когда в базах данных были более примитивные оптимизаторы хранилища, и каждый бит помогал. –

3

Важным отличием является определение произвольно большого предела (например, VARCHAR(2000)] и используя тип данных, который не требует ограничения (например, VARCHAR(MAX) или TEXT].

PostgreSQL основы все его фиксированной длины VARCHAR с на его unlimitted TEXT типа и динамически принимает решение на одно значение как хранить значение, в том числе хранить его вне страницы. Спецификатор длины в этом случае действительно является просто ограничением, и его использование фактически обескуражено. (ref)

Другие СУБД требуют, чтобы пользователь выбирал, требуется ли им «неограниченное», внестраничное хранилище, обычно с соответствующей стоимостью по удобству и/или производительности.

Если есть преимущество в использовании VARCHAR(<n>) над VARCHAR(MAX) или TEXT, то отсюда следует, что вы должны выбрать значение для <n> при проектировании таблиц. Предполагая, что существует некоторая максимальная ширина строки таблицы или записи индекса, следующие ограничения должны применяться:

  1. <n> должна быть меньше или равна <max width>
  2. если <n> = <max width>, таблица/индекс может иметь только 1 колонка
  3. в целом, таблица/индекс может иметь только <x> столбцы, где (в среднем) <n> = <max width>/<x>

это, следовательно, является не случай что значение <n> действует только как ограничение, и выбор <n> должен быть частью дизайна. (Даже если нет жестких ограничений в СУБД, могут также быть причины производительности, чтобы сохранить ширину в пределах определенного лимита.)

Вы можете использовать вышеуказанные правила, чтобы присвоить значение <n>максимум, основанный на ожидаемая архитектура вашей таблицы (с учетом влияния будущих изменений). Тем не менее, имеет смысл определить минимум значение <n>, исходя из ожидаемых данных в каждом столбце. Скорее всего, вы перейдете на ближайшее «круглое число» - например, вы всегда будете использовать либо VARCHAR(10), VARCHAR(50), VARCHAR(200), либо VARCHAR(1000), в зависимости от того, что лучше всего подходит.

+0

+1 Это относится к SQL Server (по крайней мере, 2008 г.)). Допускается только около ~ 8 тыс. «Зарезервированных данных» для каждой записи. – 2012-03-01 23:02:39

2

Простой ответ на этот вопрос, на мой взгляд, заключается в том, что вы не можете использовать этот столбец как индексный ключ, если вам требуется какая-либо индексация, вы в основном вынуждены использовать полный текст ... это касается использования varchar (max). В любом случае столбцы «правильной калибровки» имеют большой смысл, когда вы [можете] захотеть применить любую индексацию; обновление столбцов переменной длины может быть дорогостоящим маневром, поскольку они не выполняются на месте и могут/будут вызывать некоторое количество фрагментации.

Все относительно MS SQ-Server.

+0

Хм ... похоже, ты прав. Я пропустил часть об индексах на varchar (max). –

1

Если вы собираетесь печатать этикетки, вы обычно хотите, чтобы строка не превышала 35 символов. Вот почему вам нужен какой-то контроль над размером Varchar, который вы собираетесь использовать, чтобы принять строки, которые будут использоваться для печати меток.