Чи є недоліки в 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. Розподіл простору у розширеннях та сторінках бази даних є гнучким. Таким чином, додаючи інформацію в поле за допомогою оновлення, вашій базі даних доведеться створити покажчик, якщо нові дані довші за попередні вставлені. стати фрагментованим = нижча продуктивність майже у всьому, від індексу до видалення, оновлення та вставки. " 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.
Причина НЕ використовувати максимум або текстові поля полягає в тому, що ви не можете виконувати інтерактивну перебудову індексу, тобто ЗАБУДОВА З ONLINE = ВКЛ навіть у програмі SQL Server Enterprise Edition.
Єдиною проблемою, яку я виявив, було те, що ми розробляємо наші програми на SQL Server 2005, і, в одному випадку, ми повинні підтримувати SQL Server 2000. Я щойно дізнався, важкий спосіб, що SQL Server 2000 не любить опцію MAX для varchar або нварчар.
Погана ідея, коли ви знаєте, що поле буде в заданому діапазоні, наприклад, від 5 до 10 символів. Я думаю, що використовував би макс, лише якщо не був би впевнений, якою буде довжина. Наприклад, номер телефону ніколи не буде перевищувати певну кількість символів.
Чи можете ви чесно сказати, що ви не впевнені у вимогах приблизної довжини для кожного поля вашої таблиці?
Я розумію, хоча є декілька полів, які я б, звичайно, міг би використати varchar (max).
Цікаво, що документи MSDN підсумовують це досить добре:
Використовуйте varchar, коли розміри записів даних стовпців значно відрізняються. Використовуйте varchar (max), коли розміри записів даних стовпців значно відрізняються, а розмір може перевищувати 8000 байт.
Завдання бази даних - зберігати дані, щоб вони могли використовувати підприємство. Частина зробити ці дані корисними - це забезпечити їх значимість. Якщо дозволити комусь ввести необмежену кількість символів для свого імені, це не забезпечує значущих даних.
Побудова цих обмежень у бізнес-шарі є хорошою ідеєю, але це не гарантує, що база даних залишатиметься цілою. Єдиний спосіб гарантувати, що правила даних не будуть порушені - це застосувати їх на мінімально можливому рівні в базі даних.
Одна з проблем полягає в тому, що якщо вам доведеться працювати з декількома версіями SQL Server, MAX не завжди буде працювати. Тож якщо ви працюєте зі застарілою базою даних або будь-якою іншою ситуацією, яка включає декілька версій, краще будьте дуже обережні.
Як було зазначено вище, це насамперед компроміс між сховищем та продуктивністю. Принаймні, у більшості випадків.
Однак є принаймні ще один фактор, який слід враховувати при виборі n / varchar (Max) над n / varchar (n). Чи будуть індексуватися дані (наприклад, прізвище)? Оскільки визначення MAX вважається LOB, то все, що визначено як MAX, недоступне для індексації. і без індексу будь-який пошук, що включає дані як предикат у пункті WHERE, буде вимушений здійснити сканування повної таблиці, що є найгіршою ефективністю, яку ви можете отримати для пошуку даних.
1) Сервер SQL повинен буде використовувати більше ресурсів (виділена пам'ять та час процесора) при роботі з nvarchar (max) проти nvarchar (n), де n - число, характерне для цього поля.
2) Що це означає щодо продуктивності?
На SQL Server 2005 я запитав 13000 рядків даних із таблиці з 15 nvarchar (max) стовпцями. Я приурочував запити кілька разів, а потім змінював стовпці на nvarchar (255) або менше.
Запити до оптимізації були в середньому за 2.0885 секунд. Запити після зміни поверталися в середньому за 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, поступово складеною з рядків, сторінок (сторінок) та обсягу (s).
Що змушує мене думати про вирівнювання структури даних у C, а також те, що усвідомлення вирівнювання, як правило, вважається хорошою річчю (TM). Подібна ідея, інший контекст.
Сторінка MSDN для сторінок і розширень
Сторінка MSDN для даних про переповнення рядків
спершу я подумав про це, але потім знову подумав. Існують наслідки для продуктивності, але однаково вони служать формою документації, щоб мати уявлення про те, якого розміру поля насправді мають. І це застосовується, коли ця база даних знаходиться в більшій екосистемі. На мою думку, головне - бути вседозволеним, але тільки в межах розуму.
ок, ось мої почуття просто з питання логіки бізнесу та рівня даних. Це залежить від того, якщо ваша БД - це спільний ресурс між системами, які діляться діловою логікою, то, звичайно, це здається природним місцем для застосування такої логіки, але це не найкращий спосіб зробити це, найкращий спосіб - це надання API, це дозволяє взаємодія, яка підлягає тестуванню, зберігає ділову логіку там, де вона належить; вона тримає системи нерозв’язаними, вона зберігає ваші рівні в системі, деакульовані. Якщо, однак, ваша база даних обслуговує лише одну програму, то давайте дозволити AGILE подумати, що зараз правда? дизайн поки що. Якщо і коли потрібен такий доступ, надайте API до цих даних.
Очевидно, що це просто ідеал, якщо ви працюєте з існуючою системою, ймовірність полягає в тому, що вам потрібно буде зробити це по-різному, принаймні за короткий термін.
Це спричинить проблеми з продуктивністю, хоча, якщо ваша база даних мало, вона може ніколи не викликати фактичних проблем. Кожен запис займе більше місця на жорсткому диску, і в базі даних потрібно буде прочитати більше секторів диска, якщо ви шукаєте відразу багато записів. Наприклад, невеликий запис може вміщувати 50 у сектор, а великий - 5. Потрібно прочитати 10 разів більше даних з диска, використовуючи великий запис.
nvarchar(max)
стовпці, займає не більше місця на диску, ніж якби він був у nvarchar(100)
стовпці.