Answers:
是的,varchar(5000)
可能比varchar(255)
所有值都适合后者更糟糕。原因是SQL Server将根据表中列的声明(而非实际)大小来估计数据大小,进而估计内存授予。当您拥有时varchar(5000)
,它将假定每个值的长度为2500个字符,并根据该值保留内存。
这是我最近的GroupBy演示中的一个关于不良习惯的演示,可以使自己更容易证明(某些sys.dm_exec_query_stats
输出列需要SQL Server 2016 ,但仍应使用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];
所以,是的,请适当调整列的大小。
另外,我使用varchar(32),varchar(255),varchar(5000),varchar(8000)和varchar(max)重新运行了测试。相似的结果(单击放大),尽管32和255之间以及5,000和8,000之间的差异可以忽略不计:
这是另一个测试,它是TOP (5000)
我不断被重复使用的,具有更高再现性的测试的更改(单击放大):
因此,即使使用5,000行而不是10,000行(并且sys.all_columns中有5,000+行至少要追溯到SQL Server 2008 R2),仍观察到相对线性的进展-即使数据相同,定义的大小也越大如果要查询完全相同的查询,则需要更多的内存和更多的时间(即使它确实没有意义DISTINCT
)。
varchar(450)
和之间的区别varchar(255)
会一样吗?(或低于4000的东西?)
rowcount*(column_size/2)
。