Есть ли проблема с тем, чтобы все ваши строковые столбцы Sql Server 2008 были varchar (max)? Мои допустимые размеры строк регулируются приложением. База данных должна просто сохранять то, что я ей даю. Могу ли я снизить производительность, объявив все строковые столбцы типом varchar (max) в Sql Server 2008, независимо от того, какой размер данных в них фактически входит?
varchar (max) везде?
Ответы (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)
столбцов
Индексы не могут иметь ширину более 900 байт. Таким образом, вы, вероятно, никогда не сможете создать индекс. Если ваши данные меньше 900 байт, используйте varchar (900).
Это один недостаток: потому что он дает
- очень плохая эффективность поиска
- нет уникальных ограничений
Саймон Сабин некоторое время назад написал об этом пост. У меня нет времени брать его сейчас, но вы должны его поискать, потому что он приходит к выводу, что вы не должны использовать 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 символов, тогда обязательно ... сделайте это.
В отношении этого вопроса конкретно несколько моментов, о которых я не упоминаю.
- В 2005/2008/2008 R2, если столбец LOB включен в индекс, это заблокирует перестроение индекса в оперативном режиме.
- В 2012 году ограничение на перестроение онлайн-индекса снимается, но столбцы больших объектов не могут участвовать в новой функциональности Добавление столбцов NOT NULL в качестве онлайн-операции.
- Блокировки можно снимать дольше для строк, содержащих столбцы этого типа данных. (подробнее а>)
В моем ответе описаны еще несколько причин, по которым почему не varchar(8000)
везде.
- Ваши запросы могут закончиться запросом огромных грантов памяти, не оправданных размером данных.
- В таблице с триггерами это может предотвратить оптимизацию, когда не добавляются теги управления версиями.
Я задал подобный вопрос раньше. получил несколько интересных ответов. проверьте здесь Был один сайт, на котором парень говорил о вреде использования широких столбцов Однако, если ваши данные в приложении ограничены, мое тестирование опровергло это. Тот факт, что вы не можете создавать индексы для столбцов, означает, что я не буду использовать их все время (лично я бы вообще не стал их использовать, но в этом отношении я немного пурист). Однако, если вы знаете, что в них не так много хранится, я не думаю, что они так уж плохи. Если вы выполните какую-либо сортировку по столбцам набора записей с varchar (max) в нем (или любой широкий столбец, являющийся char или varchar), вы можете понести потери производительности. они могут быть разрешены (при необходимости) с помощью индексов, но вы не можете помещать индексы в varchar (max). Если вы хотите защитить свои столбцы от будущего, почему бы просто не поместить их во что-нибудь разумное. например, столбец имени должен состоять из 255 символов, а не максимум ... в этом роде.
Есть еще одна причина избегать использования varchar (max) для всех столбцов. По той же причине, по которой мы используем контрольные ограничения (чтобы избежать заполнения таблиц мусором, вызванным ошибочным программным обеспечением или пользовательскими записями), мы хотели бы защитить себя от любого ошибочного процесса, который добавляет гораздо больше данных, чем предполагалось. Например, если кто-то или что-то попытается добавить 3000 байтов в поле City, мы будем точно знать, что что-то не так, и захотели бы остановить процесс как можно раньше, чтобы отладить его как можно раньше. Мы также знали бы, что название города размером 3000 байт не может быть действительным и испортит отчеты и тому подобное, если мы попытаемся его использовать.
В идеале вы должны разрешать только то, что вам нужно. Это означает, что если вы уверены, что конкретный столбец (скажем, столбец с именем пользователя) никогда не будет длиннее 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 байтам для этих столбцов?