Есть ли какие-либо недостатки в SQL Server 2005 для создания всех символьных полей nvarchar (MAX) вместо явного указания длины, например, nvarchar (255)? (Помимо очевидного, что вы не можете ограничить длину поля на уровне базы данных)
Есть ли какие-либо недостатки в SQL Server 2005 для создания всех символьных полей nvarchar (MAX) вместо явного указания длины, например, nvarchar (255)? (Помимо очевидного, что вы не можете ограничить длину поля на уровне базы данных)
Ответы:
Тот же вопрос задавался на форумах MSDN:
Из оригинального поста (гораздо больше информации там):
Когда вы сохраняете данные в столбце VARCHAR (N), значения физически сохраняются таким же образом. Но когда вы сохраняете его в столбце VARCHAR (MAX), за экраном данные обрабатываются как значение TEXT. Таким образом, при работе со значением VARCHAR (MAX) требуется дополнительная обработка. (только если размер превышает 8000)
VARCHAR (MAX) или NVARCHAR (MAX) рассматривается как «тип большого значения». Типы больших значений обычно хранятся вне строки. Это означает, что строка данных будет иметь указатель на другое место, где хранится «большое значение» ...
N/VARCHAR(MAX)
", потому что есть дополнительная обработка ", только если размер превышает 8000". Таким образом, вы несете расходы только при необходимости , и ваша база данных менее ограничительна . Я читаю это неправильно? Похоже, что вы почти всегда хотите, N/VARCHAR(MAX)
а не N/VARCHAR(1-8000)
...
sp_tableoptions
: msdn.microsoft.com/en-us/library/ms173530.aspx . Типы VARCHAR (255) также могут быть вытолкнуты из строки, упомянутые «накладные расходы» могут быть точно такими же для MAX и 255. Он сравнивает типы MAX с типами TEXT, когда они различаются, как это происходит (совершенно другой API для манипулирования, другое хранилище и т. д.). В нем не упоминаются реальные различия: нет индекса, нет онлайн-операций над типами MAX
Это справедливый вопрос, и он утверждал отдельно от очевидного ...
Недостатки могут включать в себя:
Влияние на производительность Оптимизатор запросов использует размер поля для определения наиболее эффективного плана выполнения
«1. Распределение пространства в extends и страницах базы данных является гибким. Таким образом, при добавлении информации в поле с помощью update ваша база данных должна будет создать указатель, если новые данные длиннее, чем предыдущие вставленные. Это файлы базы данных будет стать фрагментированным = снизить производительность практически во всем, от индекса до удаления, обновления и вставки. " http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but-varchar_2800_max_2900_.aspx
Последствия интеграции - другим системам сложно понять, как интегрироваться с вашей базой данных. Непредсказуемый рост данных. Возможные проблемы безопасности, например, вы можете потерпеть крах системы, занимая все дисковое пространство.
Здесь есть хорошая статья: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html
varchar(max)
.
На основании ссылки, приведенной в принятом ответе, выясняется, что:
100 символов, хранящихся в nvarchar(MAX)
поле, будут сохранены, не отличаясь от 100 символов в nvarchar(100)
поле - данные будут храниться в строке, и у вас не будет лишних затрат на чтение и запись данных «вне строки». Так что не беспокойтесь там.
Если размер больше 4000, данные будут автоматически сохраняться вне строки, что вам и нужно. Так что никаких забот там тоже нет.
Тем не мение...
nvarchar(MAX)
столбцу. Вы можете использовать полнотекстовое индексирование, но не можете создать индекс для столбца для повышения производительности запросов. Для меня это закрывает дело ... это определенный недостаток - всегда использовать nvarchar (MAX).Вывод:
Если вам нужна некая «универсальная длина строки» во всей вашей базе данных, которую можно проиндексировать и которая не будет тратить пространство и время доступа, вы можете использовать ее nvarchar(4000)
.
nvarchar(max)
все время - как string
в C #? - но пункт 3) (вопрос индекса) дает ответ.
nvarchar(4000)
Иногда вы хотите, чтобы тип данных придавал некоторый смысл данным в нем.
Например, у вас есть столбец, который не должен быть длиннее, скажем, 20 символов. Если вы определите этот столбец как VARCHAR (MAX), какое-то мошенническое приложение может вставить в него длинную строку, и вы никогда не узнаете или не сможете предотвратить это.
В следующий раз, когда ваше приложение будет использовать эту строку, исходя из предположения, что длина строки является умеренной и разумной для домена, который она представляет, вы получите непредсказуемый и запутанный результат.
Я проверил некоторые статьи и нашел полезный тестовый скрипт из этого: http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx Затем изменил его, чтобы сравнить между NVARCHAR (10) против NVARCHAR (4000) против NVARCHAR (MAX) ) и я не вижу разницы в скорости при использовании указанных чисел, но при использовании MAX. Вы можете проверить самостоятельно. Надеюсь это поможет.
SET NOCOUNT ON;
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
@StartTime DATETIME;
--=====
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
Думайте об этом как о еще одном уровне безопасности. Вы можете создать свою таблицу без взаимосвязей с внешними ключами - что совершенно правильно - и обеспечить существование связанных сущностей полностью на бизнес-уровне. Однако внешние ключи считаются хорошей практикой проектирования, поскольку они добавляют еще один уровень ограничений на случай, если что-то испортится на бизнес-уровне. То же самое касается ограничения размера поля и не использования varchar MAX.
Причина НЕ использовать максимальные или текстовые поля в том, что вы не можете выполнять перестроения индексов в режиме онлайн, т.е. REBUILD WITH ONLINE = ON, даже с SQL Server Enterprise Edition.
Единственная проблема, которую я обнаружил, заключалась в том, что мы разрабатываем наши приложения на SQL Server 2005, и в одном случае мы должны поддерживать SQL Server 2000. Я только что узнал, сложный способ, которым SQL Server 2000 не нравится опция MAX для varchar или NVARCHAR.
Плохая идея, когда вы знаете, что поле будет в диапазоне от 5 до 10 символов, например. Я думаю, что использовал бы только max, если бы я не был уверен, какой будет длина. Например, номер телефона никогда не будет превышать определенное количество символов.
Можете ли вы честно сказать, что вы не уверены в приблизительных требованиях к длине для каждого поля в вашей таблице?
Я понимаю вашу точку зрения, хотя есть некоторые поля, которые я бы определенно рассмотрел с помощью varchar (max).
Интересно, что документы MSDN довольно хорошо подводят итог:
Используйте varchar, когда размеры записей данных столбца значительно различаются. Используйте varchar (max), когда размеры записей данных столбца значительно различаются, а размер может превышать 8000 байт.
Задача базы данных - хранить данные, чтобы их можно было использовать на предприятии. Частично сделать эти данные полезными, чтобы убедиться, что они значимы. Разрешение кому-либо вводить неограниченное количество символов для своего имени не гарантирует значимых данных.
Встраивание этих ограничений в бизнес-уровень - хорошая идея, но это не гарантирует, что база данных останется нетронутой. Единственный способ гарантировать, что правила данных не будут нарушены, - обеспечить их соблюдение на самом низком уровне в базе данных.
Одна из проблем заключается в том, что если вам приходится работать с несколькими версиями SQL Server, MAX не всегда будет работать. Так что, если вы работаете с устаревшими БД или любой другой ситуацией, которая включает в себя несколько версий, вам лучше быть очень осторожным.
Как указывалось выше, это прежде всего компромисс между хранением и производительностью. По крайней мере, в большинстве случаев.
Однако есть, по крайней мере, еще один фактор, который следует учитывать при выборе n / varchar (Max) вместо n / varchar (n). Будут ли данные проиндексированы (например, фамилия)? Поскольку определение MAX считается LOB, то все, что определено как MAX, недоступно для индексации. и без индекса любой поиск, включающий данные в качестве предиката в предложении WHERE, будет принудительно выполняться при сканировании полной таблицы, что является худшей производительностью, которую вы можете получить для поиска данных.
1) При работе с nvarchar (max) против nvarchar (n), где n - это число, специфичное для поля, серверу SQL придется использовать больше ресурсов (выделенная память и время процессора).
2) Что это означает в отношении производительности?
На SQL Server 2005 я запросил 13 000 строк данных из таблицы с 15 столбцами nvarchar (max). Я неоднократно синхронизировал запросы, а затем изменил столбцы на nvarchar (255) или менее.
Запросы до оптимизации в среднем составляли 2,0858 секунды. Запросы после изменения возвращались в среднем за 1,90 секунды. Это было около 184 миллисекунд улучшения по сравнению с базовым запросом select *. Это улучшение на 8,8%.
3) Мои результаты совпадают с несколькими другими статьями, в которых указано, что разница в производительности. В зависимости от базы данных и запроса процент улучшения может варьироваться. Если у вас не много одновременно работающих пользователей или очень много записей, разница в производительности не будет для вас проблемой. Однако разница в производительности будет увеличиваться по мере увеличения числа записей и одновременных пользователей.
У меня был udf, который дополнял строки и помещал вывод в varchar (max). Если это использовалось напрямую вместо приведения обратно к соответствующему размеру для настраиваемого столбца, производительность была очень низкой. Я закончил тем, что поместил udf произвольной длины с большой запиской вместо того, чтобы полагаться на всех вызывающих udf, чтобы повторно привести строку к меньшему размеру.
Если все данные в строке (для всех столбцов) никогда не будут разумно занимать 8000 или меньше символов, тогда дизайн на уровне данных должен обеспечить это.
Ядро базы данных намного эффективнее, сохраняя все из хранилища больших двоичных объектов. Чем меньше вы можете ограничить ряд, тем лучше. Чем больше строк вы можете втиснуть в страницу, тем лучше. База данных работает лучше, когда ей нужно меньше страниц.
Мои тесты показали, что есть различия при выборе.
CREATE TABLE t4000 (a NVARCHAR(4000) NULL);
CREATE TABLE tmax (a NVARCHAR(MAX) NULL);
DECLARE @abc4 NVARCHAR(4000) = N'ABC';
INSERT INTO t4000
SELECT TOP 1000000 @abc4
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
DECLARE @abc NVARCHAR(MAX) = N'ABC';
INSERT INTO tmax
SELECT TOP 1000000 @abc
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;
Интересная ссылка: зачем использовать VARCHAR, если вы можете использовать TEXT?
Речь идет о PostgreSQL и MySQL, поэтому анализ производительности отличается, но логика «явности» все еще сохраняется: зачем заставлять себя всегда беспокоиться о чем-то, что актуально небольшой процент времени? Если вы сохранили адрес электронной почты в переменной, вы бы использовали «строку», а не «строку, ограниченную 80 символами».
Главный недостаток, который я вижу, состоит в том, что, скажем, у вас есть это:
Какой из них дает вам больше информации о данных, необходимых для пользовательского интерфейса?
это
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](MAX) NULL,
[CompanyName] [nvarchar](MAX) NOT NULL,
[FirstName] [nvarchar](MAX) NOT NULL,
[LastName] [nvarchar](MAX) NOT NULL,
[ADDRESS] [nvarchar](MAX) NOT NULL,
[CITY] [nvarchar](MAX) NOT NULL,
[County] [nvarchar](MAX) NOT NULL,
[STATE] [nvarchar](MAX) NOT NULL,
[ZIP] [nvarchar](MAX) NOT NULL,
[PHONE] [nvarchar](MAX) NOT NULL,
[COUNTRY] [nvarchar](MAX) NOT NULL,
[NPA] [nvarchar](MAX) NULL,
[NXX] [nvarchar](MAX) NULL,
[XXXX] [nvarchar](MAX) NULL,
[CurrentRecord] [nvarchar](MAX) NULL,
[TotalCount] [nvarchar](MAX) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
Или это?
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](50) NULL,
[CompanyName] [nvarchar](50) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[ADDRESS] [nvarchar](50) NOT NULL,
[CITY] [nvarchar](50) NOT NULL,
[County] [nvarchar](50) NOT NULL,
[STATE] [nvarchar](2) NOT NULL,
[ZIP] [nvarchar](16) NOT NULL,
[PHONE] [nvarchar](18) NOT NULL,
[COUNTRY] [nvarchar](50) NOT NULL,
[NPA] [nvarchar](3) NULL,
[NXX] [nvarchar](3) NULL,
[XXXX] [nvarchar](4) NULL,
[CurrentRecord] [nvarchar](50) NULL,
[TotalCount] [nvarchar](50) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
Одним из недостатков является то, что вы будете проектировать вокруг непредсказуемой переменной, и вы, вероятно, будете игнорировать, а не использовать внутреннюю структуру данных SQL Server, постепенно состоящую из строк (-ов), страниц (-ов) и экстентов (-ов).
Что заставляет меня задуматься о выравнивании структуры данных в C, и то, что знание о выравнивании обычно считается хорошей вещью (TM). Схожая идея, другой контекст.
Страница MSDN для страниц и экстентов
Страница MSDN для данных переполнения строк
Сначала я думал об этом, но потом снова подумал. Это влияет на производительность, но в то же время он служит формой документации, позволяющей понять, каков размер полей. И он действует, когда эта база данных находится в большей экосистеме. На мой взгляд, ключ должен быть разрешающим, но только в разумных пределах.
хорошо, вот мои чувства просто по вопросу бизнеса и логики уровня данных. Это зависит от того, если ваша БД является общим ресурсом между системами, которые разделяют бизнес-логику, то, конечно, кажется естественным местом для применения такой логики, но это НЕ ЛУЧШИЙ способ сделать это, ЛУЧШИЙ способ - предоставить API, это позволяет проверяемое взаимодействие и сохраняющее бизнес-логику там, где оно принадлежит, оно разъединяет системы, оно разъединяет ваши уровни внутри системы. Однако, если предполагается, что ваша база данных обслуживает только одно приложение, тогда давайте рассудимся, что же это сейчас? дизайн на данный момент. Если и когда такой доступ необходим, предоставьте API для этих данных.
хотя, очевидно, это просто идеал, если вы работаете с существующей системой, скорее всего, вам придется делать это по-другому, по крайней мере, в краткосрочной перспективе.
Это вызовет проблемы с производительностью, хотя это может никогда не вызвать реальных проблем, если ваша база данных мала. Каждая запись будет занимать больше места на жестком диске, и база данных должна будет прочитать больше секторов диска, если вы просматриваете много записей одновременно. Например, небольшая запись может соответствовать 50 на сектор, а большая запись может соответствовать 5. Вам нужно будет прочитать в 10 раз больше данных с диска, используя большую запись.
nvarchar(max)
столбце, занимает не больше места на диске, чем в nvarchar(100)
столбце.