varchar(500)比varchar(8000)更有优势吗?

时间:2010-01-05 22:41:50

标签: sql sql-server tsql

我已经在MSDN论坛上阅读了这篇内容,而且我还不清楚。我认为这是正确的:Varchar(max)将存储为文本数据类型,因此存在缺陷。因此,假设您的字段可靠地低于8000个字符。像我的数据库表中的BusinessName字段。实际上,商业名称可能总是在(从我的帽子里拿出一个数字)500个字符。看起来我运行的大量varchar字段远低于8k字符数。

那么我应该将该字段设为varchar(500)而不是varchar(8000)吗?根据我对SQL的理解,这两者之间没有区别。因此,为了简化生活,我想将所有varchar字段定义为varchar(8000)。这有什么缺点吗?

相关:Size of varchar columns(我不觉得这个回答了我的问题)。

5 个答案:

答案 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

Screenshot

SELECT id,name8000
FROM T
ORDER BY number

Screenshot

答案 1 :(得分:18)

从处理的角度来看,使用varchar(8000)和varchar(500)并没有什么区别。定义字段应该保持的最大长度并使varchar成为一个长度,这更像是一种“良好实践”。它可用于协助数据验证。例如,将州名缩写为2个字符或邮政/邮政编码为5或9个字符。当您的数据与字段长度很关键的其他系统或用户界面(例如大型机平面文件数据集)进行交互时,这曾经是一个更重要的区别,但现在我认为它比其他任何东西都更习惯。

答案 2 :(得分:9)

除了最佳实践(BBlake的回答)

  • 使用DDL收到有关最大行大小(8060)字节和索引宽度(900字节)的警告
  • 如果超出这些限制,DML将会死亡
  • ANSI PADDING ON是默认设置,因此您最终可能会存储一大堆空白

答案 3 :(得分:9)

大型色谱柱有一些不太明显的缺点,可能会在稍后发现:

  • 您在 INDEX 中使用的所有列不得超过900字节
  • ORDER BY 子句中的所有列不得超过8060个字节。这有点难以掌握,因为这仅适用于某些列。有关详细信息,请参阅SQL 2008 R2 Row size limit exceeded
  • 如果总行数超过8060字节,则会为该行获得“页面溢出”。这可能会影响性能(一个页面是SQLServer中的一个分配单元,固定为8000字节+一些开销。超过这个不会很严重,但它是显而易见的,你应该尽量避免使用它)
  • 许多其他内部数据结构,缓冲区和最后 - 至少您自己的变量和表变量都需要镜像这些大小。如果尺寸过大,过多的内存分配会影响性能

作为一般规则,请尝试保持列宽。如果它成为问题,您可以轻松扩展它以满足需求。如果您稍后发现内存问题,稍后缩小宽列可能会变得不可能而不会丢失数据,您将不知道从哪里开始。

在您的商家名称示例中,请考虑显示它们的位置。真的有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内部的东西保留了一定数量的这些字节。