jco*_*lum 89 sql t-sql sql-server
我已经在MSDN论坛和这里读到了这个,我还不清楚.我认为这是正确的:Varchar(max)将存储为文本数据类型,因此存在缺陷.因此,假设您的字段可靠地低于8000个字符.像我的数据库表中的BusinessName字段.实际上,商业名称可能总是在(从我的帽子里拿出一个数字)500个字符.看起来我运行的大量varchar字段远低于8k字符数.
那么我应该将该字段设为varchar(500)而不是varchar(8000)吗?根据我对SQL的理解,这两者之间没有区别.因此,为了简化生活,我想将所有varchar字段定义为varchar(8000).这有什么缺点吗?
相关:varchar列的大小(我不觉得这个回答了我的问题).
Mar*_*ith 122
这可以产生影响的一个示例是,它可以阻止性能优化,避免将行版本控制信息添加到具有after触发器的表中.
存储的数据的实际大小并不重要 - 重要的是潜在的大小.
类似地,如果自2016年以来使用内存优化表,则可以使用LOB列或列宽的组合,这些列可能会超出inrow限制但会有惩罚.
(Max)列始终存储在行外.对于其他列,如果表定义中的数据行大小超过8,060字节,则SQL Server会将最大的可变长度列推送到行外.同样,它不依赖于您存储在那里的数据量.
过度声明列宽可以产生很大差异的另一种情况是,是否将使用SSIS处理表.为可变长度(非BLOB)列分配的内存对于执行树中的每一行是固定的,并且是根据列声明的最大长度,这可能导致内存缓冲区的低效使用(示例).虽然SSIS包开发人员可以声明比源更小的列大小,但这种分析最好先预先完成并在那里强制执行.
回到SQL Server引擎本身,类似的情况是,在计算为SORT
操作分配的内存授权时,SQL Server假定varchar(x)
列平均消耗x/2
字节.
如果您的大多数varchar
列都比这更完整,这可能会导致sort
操作溢出tempdb
.
在你的情况下,如果你的varchar
列被声明为8000
字节,但实际上内容远远少于你的查询将被分配它不需要的内存,这显然是低效的,并可能导致等待内存授予.
这可以在SQL Workshops Webcast 1的第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
Run Code Online (Sandbox Code Playgroud)
SELECT id,name8000
FROM T
ORDER BY number
Run Code Online (Sandbox Code Playgroud)
BBl*_*ake 18
从处理的角度来看,使用varchar(8000)和varchar(500)并没有什么区别.定义字段应该保持的最大长度并使varchar成为一个长度,这更像是一种"良好实践".它可用于协助数据验证.例如,将州名缩写为2个字符或邮政/邮政编码为5或9个字符.当您的数据与字段长度至关重要的其他系统或用户界面(例如,大型机平面文件数据集)进行交互时,这曾经是一个更重要的区别,但现在我认为它比其他任何东西更习惯.
除了最佳实践(BBlake的答案)
对于不太明显的大型列而言,存在一些缺点,可能会稍后发现:
作为一般规则,尽量保持列宽.如果它成为问题,您可以轻松扩展它以满足需求.如果您稍后发现内存问题,稍后缩小宽列可能会变得不可能而不会丢失数据,您将不知道从哪里开始.
在您的商家名称示例中,请考虑显示它们的位置.真的有500个字符的空间吗?如果没有,那么存储它们就没有什么意义了.http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States列出了一些公司名称,最大值约为50个字符.所以我最多使用100作为列.也许更像80.
归档时间: |
|
查看次数: |
33551 次 |
最近记录: |