Оскільки в varcharбудь-якому випадку динамічно розподіляти простір, моє питання полягає в тому, чи використовувати varchar(255)ефективніше чи економити більше місця в порівнянні з використанням varchar(5000). Якщо так, то чому?
Оскільки в varcharбудь-якому випадку динамічно розподіляти простір, моє питання полягає в тому, чи використовувати varchar(255)ефективніше чи економити більше місця в порівнянні з використанням varchar(5000). Якщо так, то чому?
Відповіді:
Так, varchar(5000)може бути гірше, ніж varchar(255)якщо всі значення впишуться в останні. Причина полягає в тому, що SQL Server оцінить розмір даних і, в свою чергу, пам'ять надає на основі заявленого (не фактичного ) розміру стовпців таблиці. Коли у вас з'явиться varchar(5000), буде прийнято вважати, що кожне значення має 2500 символів, і резервуйте пам'ять, виходячи з цього.
Ось демонстрація моєї недавньої презентації GroupBy про шкідливі звички, яка полегшує доведення для себе (потрібен SQL Server 2016 для деяких sys.dm_exec_query_statsвихідних стовпців, але все-таки повинен бути доступним для використання SET STATISTICS TIME ONчи іншими інструментами на попередніх версіях); він показує більший об'єм пам'яті та більш тривалість виконання для одного і того ж запиту проти тих самих даних - різниця лише в оголошеному розмірі стовпців:
-- create three tables with different column sizes
CREATE TABLE dbo.t1(a nvarchar(32), b nvarchar(32), c nvarchar(32), d nvarchar(32));
CREATE TABLE dbo.t2(a nvarchar(4000), b nvarchar(4000), c nvarchar(4000), d nvarchar(4000));
CREATE TABLE dbo.t3(a nvarchar(max), b nvarchar(max), c nvarchar(max), d nvarchar(max));
GO -- that's important
-- Method of sample data pop : irrelevant and unimportant.
INSERT dbo.t1(a,b,c,d)
SELECT TOP (5000) LEFT(name,1), RIGHT(name,1), ABS(column_id/10), ABS(column_id%10)
FROM sys.all_columns ORDER BY object_id;
GO 100
INSERT dbo.t2(a,b,c,d) SELECT a,b,c,d FROM dbo.t1;
INSERT dbo.t3(a,b,c,d) SELECT a,b,c,d FROM dbo.t1;
GO
-- no "primed the cache in advance" tricks
DBCC FREEPROCCACHE WITH NO_INFOMSGS;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
GO
-- Redundancy in query doesn't matter! Just has to create need for sorts etc.
GO
SELECT DISTINCT a,b,c,d, DENSE_RANK() OVER (PARTITION BY b,c ORDER BY d DESC)
FROM dbo.t1 GROUP BY a,b,c,d ORDER BY c,a DESC;
GO
SELECT DISTINCT a,b,c,d, DENSE_RANK() OVER (PARTITION BY b,c ORDER BY d DESC)
FROM dbo.t2 GROUP BY a,b,c,d ORDER BY c,a DESC;
GO
SELECT DISTINCT a,b,c,d, DENSE_RANK() OVER (PARTITION BY b,c ORDER BY d DESC)
FROM dbo.t3 GROUP BY a,b,c,d ORDER BY c,a DESC;
GO
SELECT [table] = N'...' + SUBSTRING(t.[text], CHARINDEX(N'FROM ', t.[text]), 12) + N'...',
s.last_dop, s.last_elapsed_time, s.last_grant_kb, s.max_ideal_grant_kb
FROM sys.dm_exec_query_stats AS s CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t
WHERE t.[text] LIKE N'%dbo.'+N't[1-3]%' ORDER BY t.[text];
Отже, так , будь ласка, розміруйте свої колонки потрібного розміру .
Також я повторно провів тести з варчаром (32), варчаром (255), варчаром (5000), варчаром (8000) та варчаром (макс.). Подібні результати ( натисніть, щоб збільшити ), хоча різниці між 32 і 255, і між 5000 і 8000, були незначними:
Ось ще один тест зі TOP (5000)зміною для більш повністю відтворюваного тесту, про який я невпинно бракував ( натисніть, щоб збільшити ):
Тож навіть при 5000 рядках замість 10 000 рядків (а в sys.all_columns є 5000+ рядків, щонайменше, як і у SQL Server 2008 R2) спостерігається відносно лінійна прогресія - навіть із тими ж даними, чим більший визначений розмір стовпця, тим більше пам’яті та часу потрібно для задоволення того самого запиту (навіть якщо він має безглуздий характер DISTINCT).
varchar(450)і varchar(255)була однаковою? (Або щось нижче 4000?)
rowcount*(column_size/2).