由于varchar无论如何动态分配空间,我的问题是varchar(255)与使用varchar(5000). 如果是,为什么?
Aar*_*and 60
是的,varchar(5000)可能比varchar(255)所有值都适合后者更糟糕。原因是 SQL Server 将根据表中列的声明(非实际)大小估计数据大小,进而估计内存授予。当您有 时varchar(5000),它将假定每个值的长度为 2,500 个字符,并基于此保留内存。
这是我最近的 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];
Run Code Online (Sandbox Code Playgroud)
所以,是的,请调整您的列的大小。
此外,我使用 varchar(32)、varchar(255)、varchar(5000)、varchar(8000) 和 varchar(max) 重新运行了测试。类似的结果(点击放大),尽管 32 和 255 之间以及 5,000 和 8,000 之间的差异可以忽略不计:
这是另一个测试,TOP (5000)更改了更完全可重复的测试,我一直在烦恼(点击放大):
因此,即使是 5,000 行而不是 10,000 行(至少在 SQL Server 2008 R2 之前,sys.all_columns 中有 5,000 多行),也观察到了相对线性的进展——即使数据相同,定义的大小也越大列,满足完全相同的查询需要更多的内存和时间(即使它确实有一个毫无意义的DISTINCT)。
| 归档时间: |
|
| 查看次数: |
14734 次 |
| 最近记录: |