我已经在MSDN论坛上阅读了这篇内容,而且我还不清楚。我认为这是正确的:Varchar(max)将存储为文本数据类型,因此存在缺陷。因此,假设您的字段可靠地低于8000个字符。像我的数据库表中的BusinessName字段。实际上,商业名称可能总是在(从我的帽子里拿出一个数字)500个字符。看起来我运行的大量varchar字段远低于8k字符数。
那么我应该将该字段设为varchar(500)而不是varchar(8000)吗?根据我对SQL的理解,这两者之间没有区别。因此,为了简化生活,我想将所有varchar字段定义为varchar(8000)。这有什么缺点吗?
相关:Size of varchar columns(我不觉得这个回答了我的问题)。
答案 0 :(得分:118)
这可以产生影响的一个例子是它可以阻止性能优化,避免向具有after触发器的表添加行版本控制信息。
This is covered by SQL Kiwi here
存储的数据的实际大小并不重要 - 这是潜在的 重要的是。
同样,如果自2016年以来使用内存优化表,则可以使用LOB列或列宽组合,这些列可能会超出inrow限制但会受到惩罚。
(Max)列始终存储在行外。对于其他列,如果表定义中的数据行大小超过8,060字节,则SQL Server会将最大的可变长度列推送到行外。同样,它不依赖于您存储的数据量。
This can have a large negative effect on memory consumption and performance
另一种过度声明列宽可能产生重大影响的情况是,是否可以使用SSIS处理表。为可变长度(非BLOB)列分配的内存对于执行树中的每一行是固定的,并且是根据列声明的最大长度,这可能导致内存缓冲区(example)的低效使用。虽然SSIS包开发人员可以声明一个比源更小的列大小,但这个分析最好先预先完成并在那里强制执行。
回到SQL Server引擎本身,类似的情况是,在计算为SORT
操作分配的内存授权时,SQL Server假定varchar(x)
列平均消耗x/2
个字节。
如果您的大多数varchar
列都比这更完整,则可能会导致sort
操作溢出tempdb
。
在您的情况下,如果您的varchar
列被声明为8000
个字节,但实际上内容远远少于您的查询,则会为您的查询分配不需要的内存,这显然效率低下且可能导致等待记忆补助。
这将在SQL Workshops网络广播1 downloadable from here的第2部分中介绍,或者参见下文。
use tempdb;
CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))
INSERT INTO T
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values
SELECT id,name500
FROM T
ORDER BY number
SELECT id,name8000
FROM T
ORDER BY number
答案 1 :(得分:18)
从处理的角度来看,使用varchar(8000)和varchar(500)并没有什么区别。定义字段应该保持的最大长度并使varchar成为一个长度,这更像是一种“良好实践”。它可用于协助数据验证。例如,将州名缩写为2个字符或邮政/邮政编码为5或9个字符。当您的数据与字段长度很关键的其他系统或用户界面(例如大型机平面文件数据集)进行交互时,这曾经是一个更重要的区别,但现在我认为它比其他任何东西都更习惯。
答案 2 :(得分:9)
除了最佳实践(BBlake的回答)
答案 3 :(得分:9)
大型色谱柱有一些不太明显的缺点,可能会在稍后发现:
作为一般规则,请尝试保持列宽。如果它成为问题,您可以轻松扩展它以满足需求。如果您稍后发现内存问题,稍后缩小宽列可能会变得不可能而不会丢失数据,您将不知道从哪里开始。
在您的商家名称示例中,请考虑显示它们的位置。真的有500个字符的空间吗?如果没有,那么存储它们就没有什么意义了。 http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States列出了一些公司名称,最大值约为50个字符。所以我最多使用100作为列。也许更像80.
答案 4 :(得分:2)
理想情况下,您希望小于此值,缩小到合理大小的长度(500的大小不合理),并确保在数据太大并发送有用错误时捕获客户端验证。
虽然varchar实际上不会在数据库中为未使用的空间保留空间,但我记得SQL Server的版本有一个关于数据库行的snit比某些字节数更宽(不记得确切的计数)和实际上丢弃了任何不合适的数据。为SQL Server内部的东西保留了一定数量的这些字节。