有关SQL Server中varchar大小调整的当前最佳实践是什么?


12

从存储和性能的角度来看,我试图了解确定varchar列应为多少的最佳方法。

表现
从我的研究看来只有真正需要时才应使用varchar(max);也就是说,如果该列必须容纳8000个以上的字符,那么一个原因就是缺乏索引(尽管一般而言,我对varchar字段的索引有些怀疑。尽管我对DB原理还很陌生,所以也许这是没有根据的)和压缩(更多有关存储的问题)。实际上,一般而言,当执行varchar(n).... oversizing不好时,人们似乎只建议使用所需的内容,因为查询必须考虑最大可能的大小。但也有人指出,引擎将使用指示大小的一半作为数据的平均实际大小的估计值。这意味着应该从数据中确定平均大小是多少,将其加倍,并将其用作n。但是,对于变异性非常低但非零的数据,这意味着要比最大尺寸大2倍,这似乎很多,但也许不是吗?见识将不胜感激。

存储
在阅读了行内存储与行外存储的工作原理并记住实际存储仅限于实际数据之后,在我看来,实际上,n的选择对存储几乎没有影响(除了确保它足够大以容纳所有东西)。即使使用varchar(max)也不会对存储产生任何影响。相反,如果可能的话,目标可能是将每个数据行的实际大小限制为〜8000字节。那是对事物的准确阅读吗?

上下文
我们的某些客户数据有些波动,因此,我们通常将列的宽度设置为稍稍超出其宽度(例如,将这些列增加15-20%)。我想知道是否还有其他特殊考虑?例如,与我一起工作的某人告诉我使用2 ^ n-1的大小(尽管我发现没有证据表明这是事实....)

我说的是初始表的创建。客户将告诉我们,他们将开始向我们发送一个新表,并发送示例数据(或仅发送第一个生产数据集),我们将对其进行查看并最终创建一个表来保存数据。我们希望使这张表最终能够处理将来的进口以及样品中的进口商品。但是,某些行注定会变长,因此我们填充它们。

问题是多少,是否有技术准则?


MongoDB使用2 ^ n磁盘分配文档。SQL Server不使用此策略。
迈克尔·格林

Answers:


19

无论特定的数据类型如何,您都需要能够存储应用程序要求存储的任何内容。您不能指定小于实际保存的最大大小的内容。

您也不需要,也不希望指定的列长度大于将要存储的最大实际大小,原因有多种:查询内存分配,可能填满最大行大小并且不留任何空间在其中添加列未来等

的确,可变长度的字符串和二进制列没有固定长度数据类型(字符串/二进制/数字/日期/等)具有存储含义(尽管其中某些含义可以通过数据压缩或使用SPARSE列定义来消除)选项)。但是,正如您所指出的那样,即使没有直接的存储含义,也仍然存在过高估计查询所需内存的性能含义。

懂事 仅使用您需要的东西。如果在不久的将来很有可能需要增加列长度,则可以考虑,但是请记住,扩大列的大小比减小大小更容易。是的,将涉及一些工作,但是由于该工作仅是“潜在的”,而过大的性能影响是“实际的”,因此通常最好根据实际需要而不是可能的种类来定义列。 -sorta认为您将来可能需要。谈论的许多更改永远不会发生,而且经常无法预见所需的更改。跟着你所知道的去。

相反,如果可能的话,目标可能是将每个数据行的实际大小限制为〜8000字节。

我不确定你在这里得到什么。SQL Server实际上将限制您到8000个字节以上。使用LOB类型- ,VARCHAR(MAX)NVARCHAR(MAX)VARBINARY(MAX)XML和弃用TEXTNTEXTIMAGE类型-允许超越该初始页面尺寸的限制,但是,这只是由于放置一个指针(16首或更多个字节,根据其种类,并根据使用MAX类型时,按行存储的值的大小)。数据页的实际物理限制未更改。

您的目标应该是使用最少的物理空间来存储应用程序/业务需要存储的内容,而不会中断或截断,以使不完整的值失去意义或导致下游问题。如果您需要存储12,000个字符的东西,请使用,VARCHAR(MAX)因为这是必需的。如果您存储的是电话号码或邮政编码,那么使用它是不明智的VARCHAR(100),并且是不负责任的VARCHAR(MAX)

我们的一些客户数据有些波动,因此我们通常将色谱柱的宽度稍宽一些,例如,将这些色谱柱的宽度扩大15-20%。我想知道是否还有其他特殊考虑?

并非所有系统都至少有一些波动的数据吗?任何存储人员姓名的系统都可以,对吗?名称长度有相当大的差异。然后,您有了像Prince这样的人,将其名称更改为符号,现在您遇到了一个完全不同的问题,那就是长度。事情就是这样。

但是,暂时扮演魔鬼的拥护者:“比需要的大15-20%”的值怎么可能不是实际需要的值呢?假设正在讨论有关添加新列的问题,有人建议输入50个字符,然后有人说:“嗯,60个字符要多20%,所以我们做60个,因为有人可能有60个字符。” 如果确实有一个客户可能有60个客户,那么60个(并且始终是)实际需要的值,而50个始终都是错误的。

当然,如果有关于数据源的某种指示,这将有所帮助,因为:

  1. 如果您将“ URL”设置为1024,而某人需要1060,则必须设置为1060(类似地,如果您创建URL VARCHAR并抱怨它弄乱了域名中现在允许的Unicode字符,则必须为NVARCHAR),但
  2. 如果有人想在500个字符限制的注释字段中添加1000个字符,那么它仍然只需要为500个即可。人们在注释中可以不那么冗长(对我来说是一个巨大的挑战;-),但ProductSKU最好足够大以适合所有人客户的SKU。

我说的是初始表的创建。客户将告诉我们,他们将开始向我们发送新表,并发送示例数据(或仅是第一个生产数据集),我们将对其进行查看并在端部创建一个表来保存数据。我们希望使表格最终可用以处理将来的导入以及示例中的内容。但是,某些行注定会变长,因此我们填充它们。问题是多少,是否有技术准则?

您在这里做了很多假设。当然,某些领域可能会变得更大。但是话又说回来,他们可能不会。或者,有些可能变小。有些人可以从非Unicode变为Unicode(一旦他们意识到世界越来越小,并且不能假设姓氏将只具有基本的ASCII /美国英语字符)。或者,他们可以停止发送字段。或者他们将来可以添加一个或多个字段。这与其他事物的任何组合。那么,为什么只关注VARCHAR列呢?如果他们当前正在发送一个INT值,并且在一两年内达到最大值并开始发送一个值,该BIGINT怎么办?如果他们有一个值为0-5的“状态”字段,该怎么办?INT哪个是“填充的”,因为它可以增长,但应该是TINYINT

您唯一可以安全预测的是,试图预测客户数据的变化方式将是错误的,而不是正确的。正确是运气/巧合(如果不是运气,那就去玩彩票吧)。

因此,准则是:

  1. 不要浪费时间和精力尝试回答一个无法回答的问题。
  2. 相反,应集中精力获取有关客户实际数据的尽可能多的信息,然后再去处理(即数据驱动的决策;-)。

您已经有了示例数据,太好了。但是,请不要忘记您也拥有客户的联系信息:电话和/或电子邮件。与他们联系!询问他们的数据规格(就像您的系统一样,他们系统中当前的数据最大长度为35,但是他们的系统将其定义为VARCHAR(50),并且他们的系统将接受最大长度,在这种情况下,您应该使用50)。并且,询问他们是否有近期计划以及这些数据类型(类型和/或大小)的更改。


1
我同意所罗门(@ Aristotle2600)-但是,您可能需要看一下对有关a varchar(255)和a 之间差异的问题的回答,以varchar(256)作进一步考虑
Max Vernon

谢谢,我给人的感觉是这样的,“只使用您需要的内容”就是全方位的良好资源管理实践。但是,我们的某些客户数据会有所波动,因此我们通常使列的宽度略大于所需的宽度,例如,将这些列的宽度扩大15-20%。我想知道是否还有其他特殊考虑?例如,与我一起工作的某人告诉我使用2 ^ n-1的大小(尽管我找不到证据证明这是事实....)。但这听起来好像没有什么要保持尽可能小。
aristotle2600

1
@ aristotle2600不知道如何应用“ 2 ^ n-1”,但是我仍然要问:理论上是否有可能制造出比需要的大的东西?那不是更大的15-20%尺寸尺寸,它需要的是不会打破?;-)。我敢肯定,如果您在数据源中更明确的话会有所帮助,因为a)如果您将“ URL”设置为1024,而某人需要1060,则需要为1060,但是b)如果有人要添加1000 chars到500个char-limit注释字段,那么它仍然只需要为500。人们可以在注释中输入更少的内容,但是产品SKU最好足够大。
所罗门·鲁茨基

@ aristotle2600我刚刚在这里将您的一些评论添加到了问题中,因为它们提供了良好的上下文。我还在回答的末尾添加了一些内容:)
所罗门·鲁兹基

非常感谢您的回答!是的,名称和地址各不相同。至于不断增加的20%的悖论,我确实明白您的意思,但是我在谈论初始表的创建。客户将告诉我们,他们将开始向我们发送新表格,并发送示例数据(或仅发送第一个生产数据集),我们将对其进行观察并最终创建一个表格来保存数据。我们希望使表格最终可用以处理将来的导入以及示例中的内容。但是,某些行注定会变长,因此我们填充它们。问题是多少,是否有技术准则?
aristotle2600
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.