在一个 关于 TDWTF 的讨论稍显激烈 出现了关于数据库中 varchar 列的大小的问题。

例如,采用包含人名的字段(只有姓名,没有姓氏)。很容易看出,这不会很长。大多数人的名字少于10个字符,很少有人超过20个字符。如果您将列设为 varchar(50),那么它肯定会包含您遇到的所有名称。

然而,对于大多数 DBMS,无论您创建 varchar(50) 还是 varchar(255),大小或速度都没有区别。

那么为什么人们试图让他们的专栏尽可能小呢?我知道在某些情况下您可能确实想对字符串的长度进行限制,但大多数情况并非如此。只有在极少数情况下,一个人的名字很长,更大的余量才会有利。


添加: 人们希望引用“大小或速度没有差异”的声明。好的。他们来了:

对于 MSSQL: http://msdn.microsoft.com/en-us/library/ms176089.aspx

存储大小为输入数据的实际长度+2字节。

对于 MySQL: http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

如果列值需要 0 – 255 字节,则 L + 1 字节;如果值可能需要超过 255 字节,则 L + 2 字节

我找不到 Oracle 的文档,也没有使用过其他 DBMS。但我没有理由相信那里有什么不同。

有帮助吗?

解决方案

我只能代表甲骨文发言。如果您输入值“SMITH”,则 VARCHAR2(50) 和 VARCHAR2(255) 占用完全相同的空间量并且执行相同的操作。

然而,将所有文本列声明为 VARCHAR2(4000) 通常不是一个好主意,因为列长度实际上是另一个约束。约束是业务规则的数据库实现,因此它们绝对应该在数据库方面定义。

举个例子。您在列上定义 CHECK 约束,以便它只能接受“Y”和“N”值。这使您的应用程序不必处理“y”和“n”,甚至“1”和“0”。检查约束可确保您的数据符合预期标准。然后,您的应用程序代码可以对其必须处理的数据的性质做出有效的假设。

列长度​​定义也是同样的情况。您将某些内容声明为 VARCHAR2(10),因为您不希望它接受“ABC123ZYX456”条目(无论出于何种原因!)

在澳大利亚,我将 STATE 列定义为 varchar2(3),因为我不希望人们输入“新南威尔士州”或“南澳大利亚州”。列定义几乎强制将它们输入为“NSW”和“SA”。从这个意义上说,VARCHAR2(3) 几乎与实际指定 CHECK IN('NSW'、'SA'、'VIC' 等)约束一样是检查约束。

简而言之,适当的列长度是编码业务规则的一种方式。它们是另一种形式的约束。它们带来了约束的所有优点(并遭受许多相同的缺点)。它们在一定程度上确保了一定程度的“数据清洁度”,“适当的”约束也有帮助。

我也不同意这种观点,即最好将此类内容保留在客户端应用程序中,因为那里更容易更改。有 20,000 人使用某个应用程序,即 20,000 次更新。您拥有一个数据库,即一次更新。如果“更容易更改客户端应用程序”这一论点为真,则可能意味着数据库将被视为一个巨大的位桶,所有巧妙的逻辑都在客户端代码中处理。这是一个值得讨论的话题,但由于所有 RDBMS 都允许您在数据库本身中定义约束等,因此很明显,至少有一个有价值的案例表明这种基本逻辑属于后端。

其他提示

我听到查询优化的确实采取VARCHAR长度考虑,虽然我不能找到一个参考。

定义一个varchar长度有助于通信的意图。越约束上定义的,更可靠的数据。

那么为什么人们试图让他们的专栏尽可能小呢? 我不主张将它们做得尽可能小,而是适当调整它们的大小。使 (n)varchar 更小而不是更大的一些原因:

1) 对于较大的字段,所有使用数据库的客户端都必须能够处理完整大小。例如,以一个保存美国地址的系统为例,每个字段包含 255 个字符:(我相信与您引用的 TDWTF 类似。)

  • 地址第一行
  • 地址行 2
  • 城市
  • 状态
  • 邮政编码

现在,您的数据输入屏幕需要允许并显示每个字段 255 个字符。不难,但对于较大的字段不太可能看起来很好打印发票,您将需要换行逻辑来处理大字段。取决于工具,没那么难。

但我不希望出现格式化信封地址的问题,该信封的每个字段或其中任何一个字段可能有 255 个字符。如果字段太长而无法容纳,您是否要截断?太棒了,有人有“House Number Streat Number”的地址第 1 行......等等等等等等 ...公寓号 111。”然后您将删除重要的公寓号。你要包起来吗?多少?如果您无法将其放入信封上的小盒子中怎么办?提出例外情况并让人手写信函吗?

2) 虽然 varchar(50) 与 varchar(255) 中保存的 10 个字符的数据不会影响大小或速度,但允许 255 个字符可以占用更多空间。如果所有字段都那么大,您可能会达到 SQL Server 2000 中的大小限制。(我还没有阅读 2005 年和 2008 年的内容,看看它们是否可以处理大于一页的行。)对于 Oracle,如果有人实际使用所有可用字符,则较大的大小允许发生行链接。

3) 索引的大小限制比叶页更严格。如果您创建的 varchar 太大,您可能会排除索引,尤其是复合索引。


另一方面,我的地址有很长的第 1 行,并且对不允许输入完整内容的网站感到沮丧。

一个重要的区别是指定任意大的限制[例如 VARCHAR(2000)],并使用不需要限制的数据类型[例如 VARCHAR(MAX) 或者 TEXT].

PostgreSQL 基于其所有固定长度 VARCHARs 无限 TEXT 类型,并动态决定 每个值 如何存储该值,包括将其存储在页外。在这种情况下,长度说明符实际上只是一个约束,实际上不鼓励使用它。 (参考)

其他 DBMS 要求用户选择是否需要“无限制”的页外存储,通常会带来便利性和/或性能方面的相关成本。

如果使用有好处的话 VARCHAR(<n>) 超过 VARCHAR(MAX) 或者 TEXT, ,因此您必须选择一个值 <n> 设计桌子时。假设表行或索引条目存在某个最大宽度,则必须应用以下约束:

  1. <n> 必须小于或等于 <max width>
  2. 如果 <n> = <max width>, ,表/索引只能有 1 列
  3. 一般来说,表/索引只能有 <x> 列(平均) <n> = <max width> / <x>

因此是 不是 的情况下 <n> 仅起到约束作用,并且选择 <n> 必须是设计的一部分。(即使您的 DBMS 中没有硬性限制,也可能出于性能原因将宽度保持在一定限制内。)

您可以使用上述规则来分配 最大限度 的价值 <n>, ,基于表的预期架构(考虑到未来更改的影响)。然而,定义 最低限度 的价值 <n>, ,基于预期 数据 在每一列中。最有可能的是,您将扩展到最接近的“整数” - 例如你总是会使用 VARCHAR(10), VARCHAR(50), VARCHAR(200), , 或者 VARCHAR(1000), ,以最合适的为准。

简单的答案,这在我看来是事实,你不能使用该列作为索引关键字,如果您需要任何索引你基本上是被迫使用全文...这是关于使用VARCHAR(最大值)柱。在任何情况下“合理精简”栏目,使有很大的意义,只要你[可]想申请任何索引;更新可变长度列可以是昂贵的操纵,因为这些不到位完成,并且可以/将导致碎裂的一些量。

所有关于MS SQ-服务器。

我会用一个问题回答你的问题:如果有一个VARCHAR(50)和一个varchar(255),为什么会在DBMS让你做一个区分之间的DBMS没有区别?为什么不是一个DBMS简单地说“使用VARCHAR最多的xxx字符和文本/ CLOB /等任何东西了这一点。”当然,或许微软/ ORACLE / IBM可能保留历史的原因,如MySQL长度的定义,但对于数据库管理系统”具有多个存储backends-为什么每一个实现自定义字符列长度?

如果你要打印你通常希望字符串超过35个字符不再标签。这就是为什么你要在VARCHAR的大小,你要使用接受一些控制 那些即将线将用于打印标签。

如果您允许的数据长度将超过255,有人链接到通过MS访问的数据的数据不能够被用来连接表(进来作为备忘录字段)。如果数据被导出到Excel它将被限制为每场255个字符。与其他软件的兼容性应该在创建数据集时予以考虑。结果 数据质量控制是所有控制数据进入您的环境。你需要什么来存储超过255个字符?有次该数据需要超过255个字符,但它们应该是远之间也很少,应使用作为可用于分析一个字段支持补充信息

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top