есть ли преимущество у varchar (500) перед varchar (8000)?

91

Я читал об этом на форумах MSDN и здесь, и мне все еще не ясно. Я думаю, что это правильно: Varchar (max) будет храниться как текстовый тип данных, поэтому у него есть недостатки. Допустим, ваше поле будет надежно содержать менее 8000 символов. Как поле BusinessName в моей таблице базы данных. На самом деле название компании, вероятно, всегда будет состоять из (вытаскивая из моей шляпы число) менее 500 символов. Похоже, что множество полей varchar, с которыми я сталкиваюсь, хорошо укладываются в число символов 8k.

Так следует ли мне сделать это поле varchar (500) вместо varchar (8000)? Насколько я понимаю, между ними нет разницы. Итак, чтобы упростить жизнь, я бы хотел определить все свои поля varchar как varchar (8000). Есть ли у этого недостатки?

Связано: Размер столбцов varchar (мне не казалось, что это ответило на мой вопрос).

Jcollum
источник
6
Представьте, что вы пытаетесь уместить название компании длиной 500 символов на визитной карточке ... :)
OMG Ponies
2
@OMG Ponies: каждый раз, когда я вижу ваше имя пользователя, я хихикаю. Итак, что вы говорили? (
Шучу
4
@jcollum: SpaceMan Spiff всегда получит мой голос. Это неправда - подойдут любые модели Calvin & Hobbes, но особенно снежные скульптуры. Или тиранозавр, летящий на F-14. Но я отвлекся ...
OMG Ponies

Ответы:

21

С точки зрения обработки не будет иметь значения использование varchar (8000) vs varchar (500). Это больше похоже на «хорошую практику» - определить максимальную длину, которую должно содержать поле, и сделать ваш varchar такой длиной. Это то, что можно использовать для проверки данных. Например, сокращение штата должно состоять из 2 символов, а почтовый индекс - из 5 или 9 символов. Раньше это было более важным различием, когда ваши данные взаимодействовали с другими системами или пользовательскими интерфейсами, где длина поля была критичной (например, набор данных плоского файла мэйнфрейма), но в настоящее время я думаю, что это больше привычка, чем что-либо еще.

BBlake
источник
3
Имеет смысл ... для вещей, которые естественно имеют максимальную длину. Но что делать, если максимальная длина не очевидна? Например, название компании.
jcollum 06
2
Для чего-то подобного, если я не предвижу никакого способа спрогнозировать, каким потенциально может быть размер, я обычно использую varchar (8000) или varchar (max), в зависимости от типа данных
BBlake,
4
Кажется, это действительно
a_horse_with_no_name
2
Более поздние ответы показывают , что есть затраты: это влияет оптимизация логического ответа Мартина Смита , а также рассмотреть 8К общие вопросы размера строки , упомянутые ГБН и Оливер .
ToolmakerSteve
124

Один из примеров, когда это может иметь значение, заключается в том, что это может предотвратить оптимизацию производительности, которая позволяет избежать добавления информации о версиях строк в таблицы с триггерами после.

Это описано в SQL Kiwi здесь

Фактический размер хранимых данных не имеет значения - имеет значение потенциальный размер.

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

(Макс.) Столбцы всегда хранятся вне строк. Для других столбцов, если размер строки данных в определении таблицы может превышать 8060 байт, SQL Server выталкивает самые большие столбцы переменной длины за пределы строки. Опять же, это не зависит от количества данных, которые вы там храните.

Это может иметь большое негативное влияние на потребление памяти и производительность.

Другой случай, когда чрезмерное объявление ширины столбца может иметь большое значение, - это то, будет ли таблица когда-либо обрабатываться с использованием SSIS. Память, выделенная для столбцов переменной длины (не BLOB), фиксируется для каждой строки в дереве выполнения и соответствует объявленной максимальной длине столбцов, что может привести к неэффективному использованию буферов памяти (пример) . Хотя разработчик пакета SSIS может объявить столбец меньшего размера, чем исходный, этот анализ лучше всего проводить заранее и применять там.

В самом ядре SQL Server похожий случай заключается в том, что при вычислении объема памяти, выделяемой для SORTопераций, SQL Server предполагает, что varchar(x)столбцы в среднем потребляют x/2байты.

Если большинство ваших varcharстолбцов заполнено больше, чем это, это может привести к тому, что sortоперации будут перенаправлены на tempdb.

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

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

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Снимок экрана

SELECT id,name8000
FROM T
ORDER BY number

Снимок экрана

Мартин Смит
источник
1
Итак, если почти все мои значения составляют 3 или 4 символа, никогда не могут превышать 4 символа, и я хочу избежать «перелива операций сортировки на tempdb», я объявлю свой столбец VARCHAR (8) и использую ограничение CHECK для принудительного применения этого столбца ширина не может превышать 4 символа. Что вы думаете?
AK
12
@AlexKuznetsov - В этой ситуации я бы объявил их, так char(4)как в любом случае накладные расходы составляют 2 байта на столбец переменной.
Мартин Смит
9

Помимо лучших практик (ответ BBlake)

  • Вы получаете предупреждения о максимальном размере строки (8060) байтов и ширине индекса (900 байтов) с DDL
  • DML умрет, если вы превысите эти пределы
  • ANSI PADDING ON по умолчанию, поэтому вы можете сохранить целую кучу пробелов
gbn
источник
38
Просто для уточнения о ANSI проклейки на: при использовании nvarcharи varcharтипов, это только означает , что конечные пробелы сохранены при вставке - не то, что эти значения дополняются пробелами до размера колонки, как в charи nchar.
Ben M
9

У больших столбцов есть некоторые недостатки, которые менее очевидны и могут вас уловить немного позже:

  • Все столбцы, которые вы используете в ИНДЕКСЕ - не должны превышать 900 байт.
  • Все столбцы в предложении ORDER BY не могут превышать 8060 байт. Это немного сложно понять, поскольку это относится только к некоторым столбцам. Дополнительные сведения см. В разделе « Превышен предел размера строки SQL 2008 R2» )
  • Если общий размер строки превышает 8060 байт, вы получаете " разлив страницы " для этой строки. Это может повлиять на производительность (страница является единицей распределения в SQLServer и имеет фиксированный размер 8000 байт + некоторые накладные расходы. Превышение этого значения не будет серьезным, но это заметно, и вам следует постараться избежать этого, если вы легко можете)
  • Многие другие внутренние структуры данных, буферы и, не в последнюю очередь, ваши собственные переменные и переменные таблицы должны отражать эти размеры. При чрезмерном размере чрезмерное выделение памяти может повлиять на производительность.

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

В вашем примере с названиями компаний подумайте, где вы можете их отображать. Есть ли место для 500 символов ?? В противном случае нет смысла хранить их как таковые. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States перечисляет названия некоторых компаний, максимальная длина составляет около 50 символов. Поэтому я бы использовал 100 для столбца max. Может, больше 80.

Оливер
источник
2

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

Хотя varchar на самом деле не собирается резервировать место в базе данных для неиспользуемого пространства, я вспоминаю версии SQL Server, в которых говорилось о том, что строки базы данных шире некоторого числа байтов (не помню точное количество) и фактически выбрасывали какие данные не подходят. Определенное количество этих байтов было зарезервировано для внутренних операций SQL Server.

Отис
источник
правда, раньше это тоже было гораздо большей проблемой. Но в настоящее время пространство действительно дешевое, поэтому я не думаю, что это серьезная проблема, по крайней мере, с моей точки зрения.
BBlake 05
1
@jcollum: В вашем примере размер 500 не кажется разумным для названия компании.
Otis
1
@BBlake: Независимо от стоимости хранилища, если у SQL Server все еще есть ограничения на размер строки, неважно, сколько у вас хранилища. Вы можете хранить все в текстовых двоичных объектах, но есть некоторые операции SQL, которые вы не можете выполнять с большим двоичным объектом, которые вы можете выполнять с помощью varchar.
Otis
2
@Otis: я хочу сказать следующее: нет фактических ограничений на размер названия компании. Если где-то нет закона. Так что в этом случае я бы сделал это поле varchar (8000) и назову его днем. Я думаю так: реальные ограничения? varchar (х). Никаких ограничений? варчар (8000).
jcollum
24
Я думал, что 30 или около того символов подходят для названий городов, пока не увидел El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC