varchar(max)无处不在?

时间:2010-01-19 05:25:07

标签: sql-server-2008 varchar

将所有Sql Server 2008字符串列varchar(max)都有问题吗?我允许的字符串大小由应用程序管理。数据库应该坚持我给它的东西。通过在Sql Server 2008中将所有字符串列声明为varchar(max)类型,无论实际进入它们的数据大小,我都会受到性能影响吗?

7 个答案:

答案 0 :(得分:45)

通过使用VARCHAR(MAX),您基本上告诉SQL Server“在此字段中存储您看到的最佳值”,然后SQL Server将选择是将值存储为常规VARCHAR还是存储为LOB (大型物件) 通常,如果存储的值小于8,000字节,SQL Server会将值视为常规VARCHAR类型。

如果存储的值太大,则允许该列将页面溢出到LOB页面,就像它们对其他LOB类型(textntext和{{1}一样。 }) - 如果发生这种情况,则需要额外的页面读取来读取存储在附加页面中的数据(即,存在性能),但是仅当存储的值太大时才会发生。 / p>

事实上,在SQL Server 2008或更高版本中,即使使用固定长度的数据类型(例如image),数据也可能溢出到其他页面上,但是这些页面称为行溢出数据页面,并且处理方式略有不同。

简短版本:从存储的角度来看,VARCHAR(3,000)VARCHAR(MAX) VARCHAR(N)使用N没有任何不利之处。

(请注意,这也适用于其他可变长度字段类型NVARCHARVARBINARY

仅供参考 - 您can't create indexes on VARCHAR(MAX) columns

答案 1 :(得分:31)

索引的宽度不能超过900字节。所以你可能永远不会创建一个索引。如果您的数据少于900字节,请使用varchar(900)。

这是一个缺点:因为它给出了

  • 搜索性能非常糟糕
  • 没有唯一约束

答案 2 :(得分:9)

西蒙萨宾在一段时间后写了这篇文章。我现在没有时间抓住它,但你应该搜索它,因为他得出的结论是你不应该默认使用varchar(max)。

编辑:Simon有一些关于varchar(max)的帖子。以下评论中的链接显示了这一点。我认为最重要的是http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx,它讨论了varchar(max)对计划缓存的影响。一般原则是要小心。如果你不需要它是max,那么不要使用max - 如果你需要超过8000个字符,那么确定......去吧。

答案 3 :(得分:5)

对于这个问题,我没有看到提到的几点。

  1. 在2005/2008/2008 R2上,如果索引中包含LOB列,则会阻止在线索引重建。
  2. 2012年,解除了在线索引重建限制,但LOB列无法参与新功能Adding NOT NULL Columns as an Online Operation
  3. 锁定可以在包含此数据类型列的行上取出更长时间。 (more
  4. 我对why not varchar(8000) everywhere的回答中提到了其他几个原因。

    1. 您的查询最终可能会请求大量的内存授予,而不是数据大小。
    2. 在带有触发器的表上,它可以阻止未添加版本标记的优化。

答案 4 :(得分:4)

我之前问了类似的问题。得到了一些有趣的回复。看看here 有一个网站有一个人谈论使用宽列的不利因素,但是如果你的数据在应用程序中有限,我的测试就反驳了它。 你无法在列上创建索引的事实意味着我不会一直使用它们(我个人根本不会使用它们,但在这方面我有点纯粹)。 但是如果你知道它们中没有太多存储,我认为它们并不那么糟糕。 如果对列进行任何排序,其中包含varchar(max)的记录集(或任何宽列为char或varchar),那么您可能会遭受性能损失。这些可以通过索引解析(如果需要),但不能将索引放在varchar(max)上。 如果您希望将来证明您的专栏,为什么不把它们放到合理的位置。例如,名称列是255个字符而不是最大......那种事情。

答案 5 :(得分:1)

理想情况下,您应该只允许您需要的内容。这意味着如果您确定某个特定列(比如用户名列)的长度永远不会超过20个字符,那么使用VARCHAR(20)和VARCHAR(MAX)可以让数据库优化查询和数据结构。

来自MSDN: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

对于这些列,你真的要接近2 ^ 31-1个字节吗?

答案 6 :(得分:1)

还有另一个原因可以避免在所有列上使用varchar(max)。出于同样的原因,我们使用检查约束(为了避免填充由错误的软件或用户条目引起的垃圾表),我们希望防止任何错误的进程添加比预期更多的数据。例如,如果某人或某事试图在城市字段中添加3,000个字节,我们肯定会知道某些事情是不对的,并且希望停止该过程死在其轨道中以尽早调试它。我们还知道,一个3000字节的城市名称可能无效,如果我们尝试使用它,会导致报告混乱。

相关问题