varchar (max) везде?

Есть ли проблема с тем, чтобы все ваши строковые столбцы Sql Server 2008 были varchar (max)? Мои допустимые размеры строк регулируются приложением. База данных должна просто сохранять то, что я ей даю. Могу ли я снизить производительность, объявив все строковые столбцы типом varchar (max) в Sql Server 2008, независимо от того, какой размер данных в них фактически входит?


person BowserKingKoopa    schedule 19.01.2010    source источник
comment
В моем чтении это звучит так, как будто столбцы varchar Sql Server автоматически изменяют размер. Так разве столбец varchar (max) с максимальной длиной любого заданного значения 20 не будет таким же, как столбец varchar (20)?   -  person BowserKingKoopa    schedule 19.01.2010


Ответы (7)


Используя VARCHAR(MAX), вы в основном говорите SQL Server «хранить значения в этом поле так, как вам лучше всего», тогда SQL Server выберет, хранить ли значения как обычные VARCHAR или как LOB (большой объект). Как правило, если сохраненные значения меньше 8 000 байт, SQL Server будет рассматривать значения как обычный VARCHAR тип.

Если сохраненные значения слишком велики, тогда столбцу разрешено перетекать со страницы на LOB-страницы, точно так же, как это происходит для других типов LOB (text, ntext и image) - если это произойдет, то для чтения данные, хранящиеся на дополнительных страницах (т. е. есть производительность), однако это происходит только в том случае, если сохраненные значения слишком велики.

Фактически в SQL Server 2008 или более поздних версиях данные могут переполняться на дополнительные страницы даже с типами данных фиксированной длины (например, VARCHAR(3,000)), однако эти страницы называются страницами данных переполнения строк и обрабатываются несколько иначе.

Краткая версия: с точки зрения хранилища нет недостатков в использовании VARCHAR(MAX) вместо VARCHAR(N) для некоторых N.

(Обратите внимание, что это также относится к другим типам полей переменной длины NVARCHAR и VARBINARY)

К вашему сведению - вы не можете создавать индексы для VARCHAR(MAX) столбцов

person Justin    schedule 27.07.2011
comment
Это может быть верно только для полей, допускающих значение NULL. Для каждого ненулевого столбца varchar (max) или nvarchar (max) требуется 24 байта дополнительного фиксированного выделения. docs.microsoft.com/en-us/sql/t-sql/data-types/ - person Liazy; 03.05.2018

Индексы не могут иметь ширину более 900 байт. Таким образом, вы, вероятно, никогда не сможете создать индекс. Если ваши данные меньше 900 байт, используйте varchar (900).

Это один недостаток: потому что он дает

  • очень плохая эффективность поиска
  • нет уникальных ограничений
person gbn    schedule 19.01.2010
comment
Но что, если в столбце varchar (max) нет значений, превышающих 900 байт? Будет ли он тогда индексироваться? Я смущен, потому что многое из того, что я читаю, заставляет типы столбцов varchar звучать так, как будто они автоматически увеличивают свой размер до максимального значения при вводе данных. Это было бы идеально для того, что я хочу, потому что максимальное значение должно определять приложение, а не база данных. - person BowserKingKoopa; 20.01.2010
comment
Вы получите предупреждение при создании индекса и ошибку при попытке вставить ›900. Но если ваши данные всегда <900, почему бы не использовать 900? Да, они хранятся в виде строк переменной длины. - person gbn; 20.01.2010
comment
Я не знаю, всегда ли мои данные <900. Это проблема бизнес-логики. Если это правило изменится, я должен изменить его в бизнес-логике. Мне также не нужно менять базу данных. В любом случае это моя цель. Чтобы увидеть, смогу ли я убрать заботу о размерах строк из базы данных без заметного снижения производительности. - person BowserKingKoopa; 20.01.2010
comment
Как часто полезно индексировать столбец с длинным текстом? Стоит ли даже индексировать что-то вроде столбца varchar (200)? В конце концов, сам индекс был бы неэффективен. Необходимость поиска по длинным точным совпадениям кажется маловероятной. И поиск по шаблону принесет пользу только в том случае, если известно начало шаблона. - person Disillusioned; 03.07.2014

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

Отредактировано: у Саймона есть несколько сообщений о varchar (max). Ссылки в комментариях ниже это прекрасно показывают. Я думаю, что наиболее важным из них является http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx, в котором говорится о влиянии varchar (max) на кеширование планов. Общий принцип - быть осторожным. Если вам не нужно, чтобы он был максимальным, не используйте максимальное значение - если вам нужно более 8000 символов, тогда обязательно ... сделайте это.

person Rob Farley    schedule 19.01.2010
comment
Этот? sqlblogcasts.com/blogs/simons/archive/2005/11/18/ - person OMG Ponies; 19.01.2010
comment
нет, вот этот: sqlblogcasts .com / blogs / simons / archive / 2006/02/28 / - person gbn; 19.01.2010
comment
Первый. Автор: OMG Ponies. - person Rob Farley; 19.01.2010
comment
Извините, у меня не было времени найти настоящую ссылку, я собирался выйти на встречу, когда мне захотелось дать ответ. - person Rob Farley; 19.01.2010
comment
И, что более важно, этот: sqlblogcasts.com/blogs/simons/archive/2009/07/11/ - person Rob Farley; 19.01.2010
comment
Похоже на ошибку, возникающую в необычной ситуации. И комментарии к статье звучат так, будто она уже исправлена ​​или будет исправлена. Это самый серьезный недостаток повсеместного использования varchar (max)? Потому что, если так, varchar (max) везде звучит неплохо. - person BowserKingKoopa; 20.01.2010
comment
Что ж, это может быть `` хорошо '' для ситуации, когда нам может внезапно понадобиться написать сочинение для чьей-то фамилии, но когда вам интересно, как SQL собирается справиться с этим в различных ситуациях (особенно при вычислениях и индексах), тогда вы обнаружите, что вы чувствуете, что «хорошее» - это просто компромисс. - person Rob Farley; 20.01.2010

В отношении этого вопроса конкретно несколько моментов, о которых я не упоминаю.

  1. В 2005/2008/2008 R2, если столбец LOB включен в индекс, это заблокирует перестроение индекса в оперативном режиме.
  2. В 2012 году ограничение на перестроение онлайн-индекса снимается, но столбцы больших объектов не могут участвовать в новой функциональности Добавление столбцов NOT NULL в качестве онлайн-операции.
  3. Блокировки можно снимать дольше для строк, содержащих столбцы этого типа данных. (подробнее )

В моем ответе описаны еще несколько причин, по которым почему не varchar(8000) везде.

  1. Ваши запросы могут закончиться запросом огромных грантов памяти, не оправданных размером данных.
  2. В таблице с триггерами это может предотвратить оптимизацию, когда не добавляются теги управления версиями.
person Martin Smith    schedule 27.12.2012

Я задал подобный вопрос раньше. получил несколько интересных ответов. проверьте здесь Был один сайт, на котором парень говорил о вреде использования широких столбцов Однако, если ваши данные в приложении ограничены, мое тестирование опровергло это. Тот факт, что вы не можете создавать индексы для столбцов, означает, что я не буду использовать их все время (лично я бы вообще не стал их использовать, но в этом отношении я немного пурист). Однако, если вы знаете, что в них не так много хранится, я не думаю, что они так уж плохи. Если вы выполните какую-либо сортировку по столбцам набора записей с varchar (max) в нем (или любой широкий столбец, являющийся char или varchar), вы можете понести потери производительности. они могут быть разрешены (при необходимости) с помощью индексов, но вы не можете помещать индексы в varchar (max). Если вы хотите защитить свои столбцы от будущего, почему бы просто не поместить их во что-нибудь разумное. например, столбец имени должен состоять из 255 символов, а не максимум ... в этом роде.

person AtaLoss    schedule 22.08.2011

Есть еще одна причина избегать использования varchar (max) для всех столбцов. По той же причине, по которой мы используем контрольные ограничения (чтобы избежать заполнения таблиц мусором, вызванным ошибочным программным обеспечением или пользовательскими записями), мы хотели бы защитить себя от любого ошибочного процесса, который добавляет гораздо больше данных, чем предполагалось. Например, если кто-то или что-то попытается добавить 3000 байтов в поле City, мы будем точно знать, что что-то не так, и захотели бы остановить процесс как можно раньше, чтобы отладить его как можно раньше. Мы также знали бы, что название города размером 3000 байт не может быть действительным и испортит отчеты и тому подобное, если мы попытаемся его использовать.

person Larry Ness    schedule 27.04.2016

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

Из MSDN: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

Собираетесь ли вы когда-нибудь приблизиться к 2 ^ 31-1 байтам для этих столбцов?

person leepowers    schedule 19.01.2010
comment
Я не думаю, что правильно называть это распределением. БД, конечно же, нигде не резервирует вам 2 ^ 31-1 байта. - person Scott Stafford; 02.04.2012
comment
столбец имени пользователя [..] никогда не должен быть длиннее 20 символов - хорошо, пока однажды заказчик не решит, что он должен быть длиннее. Мы все были там. :) - person Steve Smith; 05.09.2017