在表格中使用VARCHAR(MAX)有什么缺点吗?

34

这里是我的困境。

基本上,我需要在一个表中的一列中存储未知长度的字符。但我好奇在Sql Server中,在一个列中使用VARCHAR(MAX)或NVARCHAR(MAX)会出现性能问题,比如:“这次”我只需要存储3个字符,大部分时间我只需要存储10个字符。但有很小的可能性它可以在那一列中达到几千个字符,甚至可能有一百万个字符,这是不可预测的。但我可以保证它不会超过2GB的限制。

我只是好奇是否存在任何性能问题,或者是否有更好的解决问题的方法。

6个回答

15

听起来你打算使用varchar(MAX)数据类型来实现其预期用途。

当MAX数据类型中的数据超过8 KB时,会使用溢出页。SQL Server 2005会自动为页面分配一个溢出指示器,并知道如何处理数据行,就像处理其他数据类型一样。

如需进一步阅读,请查看Books Online:char和varchar


2
虽然完全正确,但我会避免使用术语“溢出”,因为Row-Overflow是varchar(n)的页面类型名称,而在使用DBCC Ind查看时,varchar(max)转到“Lob Data”页面类型。 - Andrew
1
那么对于“是否存在任何性能问题”的问题,答案是没有-可能只有在溢出时有一点点微不足道的影响。这是正确的吗? - Dirk Boer

11

varchar(max)(和nvarchar(max))列上无法创建索引(虽然它们可以包含在其中。但是,谁会在索引中包含一个最大可达到2GB的列呢?!)因此,如果您想要搜索这个值,每次都需要进行扫描,除非您使用全文本索引。此外,请记住,任何报表设计师或演示文稿设计师(Web或其他方式)都必须假设某人可能会将百科全书放入该列并设计环绕它。没有比听到“用户可能不会做X”更糟糕的事情了。如果用户能够做到,他们就会这样做。如果用户可以把一部著作放入某一列中,则在某个时刻,他们将会这样做。如果他们永远不应该这样做,则我认为,在某个合理的水平上限制列大小,并且如果用户试图将超过允许范围的值填入该列,这将引发一场讨论,讨论是否应该首先将该值输入该列。


1
我非常不同意。在我的经验中,用户在合理范围内遇到任意大小限制是经常发生的事情。另一方面,我从未见过有人因将整个百科全书复制到表单中而投诉的情况。 - dan04
@dan04 - 在我看来,开发人员经常没有花时间了解列的实际意图。不设置限制的问题在于用户可以将垃圾放入列中,然后抱怨报告出现错误、屏幕加载缓慢或将名字和姓氏放入单个字段中,现在无法按姓氏排序等等,因此您需要停止正在进行的工作并修复他们的数据。如果没有任何限制,那么在为时已晚之前,没有任何指示表明有人试图将某些东西塞进不该在其中的列中。 - Thomas
1
问题在于,有些人确实拥有40个字母的多连字符姓氏,而当你试图将其强制转换为VARCHAR(16)时,他们会抱怨。 - dan04
6
@dan04 - 我们在一件事情上达成了共识:我也讨厌任意大小限制。关键词在于“任意”。这意味着开发人员从未就给定列的最正确尺寸向客户或其他来源征求意见。因此,虽然我们同意 varchar(16) 对于姓氏来说太小了,但我认为 varchar(max) 对于姓氏来说同样愚蠢甚至更愚蠢。 - Thomas

4

我刚刚看到了this篇文章。它记录了varchar(max)列相对于varchar(n)列的一些性能差异,但这些差异可能不足以对您产生影响。但如果有影响,也许您可以使用单独的表来存储那些大文本块。您的小文本可以留在主表中,但您可以添加一个标志字段,告诉您在新表中查找大文本块。


4
我见过一些问题,尤其是针对标量函数的(但这些通常都很不好),它们返回varchar(MAX),然后没有重新转换。例如,假设您有一个特殊函数CleanString(somevarcharmax)返回varchar(max),并在varchar(50)上调用它,但没有CAST(CleanString(varchar10col)AS varchar(10))- 会出现性能问题。
但通常情况下,在表中有varchar(max)列时,不应进行大规模的此类操作,因此我认为,如果您在表中正确使用它以满足数据需求,则可以接受。

1

-3
不,varchar(max) 根据输入的大小自动调整大小,因此如果您将使用大小差异较大的输入,则它是最有效的。

varchar(max)实际上会分配 n 个字节长度 + 2 个字节,但实际上的问题是,即使只使用一个字节的数据,它也不允许列索引。这对于掩盖缺乏数据结构规划而言太低效了。 - alejandrob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接