定义最佳varchar长度

时间:2014-03-27 14:03:30

标签: sql sql-server sqldatatypes

我发现 varchar(20) varchar(40)在性能方面没有区别。

但后来我问自己逻辑上的问题,为什么不创建一个表格,其中所有字符列都是 varchar(4000)

在我看来,如果我的列只包含3个字符,我认为 varchar(3) varchar(4000)之间存在一些区别。但我找不到这种区别。

4 个答案:

答案 0 :(得分:2)

与Microsoft的文档中定义的存储空间没有区别。

  

varchar [(n | max)]可变长度的非Unicode字符串数据。 ñ   定义字符串长度,可以是1到8,000之间的值。最大   表示最大存储大小为2 ^ 31-1个字节(2 GB)。该   存储大小是输入数据的实际长度+ 2个字节。该   varchar的ISO同义词是char变化或字符变化。   http://technet.microsoft.com/en-us/library/ms176089.aspx

您所拥有的差异可能是糟糕的数据。应定义列以允许最大有效输入,而不仅仅允许任何内容。我看到VARCHAR(MAX)列导致数据库爆炸,因为有人运行了错误的更新语句并且每行填充了大约2 GB的数据。

运行以下查询并查看执行计划。

DECLARE @tableOne TABLE
(
 id INT
,MySmallField VARCHAR(3)
)

DECLARE @tabletwo TABLE
(
 id INT
,MyBigField VARCHAR(3000)
)

INSERT INTO @tableOne
VALUES( 0, 'aaa' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 5, 'ddd' )

INSERT INTO @tableTwo
VALUES( 0, 'aaa' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 1, 'aaa' ),( 2, 'aaa' ),( 3, 'bbb' ),( 4, 'ccc' ),( 5, 'ddd' ),( 5, 'ddd' )


SELECT * FROM @tableOne WHERE MySmallField = 'ccc'

SELECT * FROM @tabletwo WHERE MyBigField = 'ccc'

下载SQL Sentry Plan Explorer它是免费工具,为您提供比SSMS更易于使用的界面。

查看简单语句的执行计划,您将看到为插入大型列sql server添加Compute Scalar函数执行以下操作

Expr1104=CONVERT_IMPLICIT(varchar(3000),[Union1103],0 

对于此操作,数据网站从784 B升至74 KB。这只需插入50行即可完成。操作越大,这将产生巨大的影响。

答案 1 :(得分:1)

它与存储立场无关。
如果您的行filled-uptempdb ,如果您的col大小varchar列被声明为5000字节,则它只会影响您对性能进行排序实际上内容远小于你的查询将分配它不需要的内存,这显然是低效的,并可能导致等待内存授予。
 一种好方法是根据要存储的实际数据选择合理的最大长度值。

答案 2 :(得分:1)

简单的答案是"因为您需要保留的内存超过您的需要"。真的,为什么停在varchar大小?为什么不为所有内容使用单个大varbinary列?还是xml?为什么不让所有列都可以为空?为什么使用约束和外键?架构的好处正是如此 - 您可以依赖一些架构。它当然有其自身的缺陷(当然灵活性较差),但这就是为什么这不是存储数据的唯一方法(例如,文档数据库通常根本不需要架构,它提供了更大的灵活性,并且不要求你两次声明你的意图。

性能方面要复杂得多。 SQL Server用于存储数据的给定页面大小。这限制了您每页8060 B的数据。跨页面拆分数据是透明的,但它会带来性能损失。限制最大行大小可以更好地判断性能。 http://technet.microsoft.com/en-us/library/ms186981(v=sql.105).aspx更多地谈到了网页尺寸问题。

更重要的是,在考虑指数时,长度会回来咬你。 varchar(3)上的索引就好了。 varchar(4000)只是荒谬。它会影响您在查找和插入时的性能,而且您真的不想要它。

稀疏列使事情进一步复杂化。在存储过程(和查询)参数上具有合理的大小也很方便。所有这些事情往往会阻止你犯下愚蠢的错误,更不用说它们有助于防止巨魔输入不合理的数据:)

最后,我们的想法是尽可能多地为引擎提供信息,以确保您获得所需的效果"。

答案 3 :(得分:0)

  

正如一些用户所解释的那样,VARCHAR(10)将具有相同的功能   性能如VARCHAR(1000),我认为这不完全正确。

     

VARCHAR(10)表示您可以在该字段中存储UPTO 10字符。   VARCHAR(1000)表示您可以在该字段中存储最多1000个字符。

     

现在,如果sql server必须从具有列的表中提取数据   数据类型VARCHAR(1000)但只存储了10个字符串长字符串   它。是的,在这种情况下,性能将与将具有的相同   是一个VARCHAR(10)专栏。

     

但是说VARCHAR(1000)将具有与VARCHAR(10)相同的性能,即使VARCHAR(1000)中存储的字符数超过10个。   这根本不是真的。我看到这些允许的字符长度更多   阻止垃圾数据进入的约束。