varchar(max) везде?
Есть ли проблема с тем, чтобы все ваши строковые столбцы в Sql Server 2008 были varchar(max)? Мои допустимые размеры строк управляются приложением. База данных должна просто сохранять то, что я даю. Получу ли я снижение производительности, объявив в Sql Server 2008 все строковые столбцы типа varchar (max), независимо от размера данных, которые на самом деле поступают в них?
7 ответов
Используя VARCHAR(MAX)
вы в основном говорите SQL Server "хранить значения в этом поле так, как вы считаете нужным", затем SQL Server будет выбирать, сохранять ли значения как обычные VARCHAR
или как большой объект (большой объект). Как правило, если сохраненные значения меньше 8000 байт, SQL Server будет рассматривать значения как обычные VARCHAR
тип.
Если хранимые значения слишком велики, столбцу разрешается выделять страницу на страницы больших объектов, точно так же, как и для других типов больших объектов (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, если столбец большого объекта включен в индекс, это заблокирует перестроения индекса онлайн.
- В 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 байтам для этих столбцов?