为 (n)varchar 列选择什么大小?
-
12-09-2019 - |
题
在一个 关于 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 基于其所有固定长度 VARCHAR
s 无限 TEXT
类型,并动态决定 每个值 如何存储该值,包括将其存储在页外。在这种情况下,长度说明符实际上只是一个约束,实际上不鼓励使用它。 (参考)
其他 DBMS 要求用户选择是否需要“无限制”的页外存储,通常会带来便利性和/或性能方面的相关成本。
如果使用有好处的话 VARCHAR(<n>)
超过 VARCHAR(MAX)
或者 TEXT
, ,因此您必须选择一个值 <n>
设计桌子时。假设表行或索引条目存在某个最大宽度,则必须应用以下约束:
<n>
必须小于或等于<max width>
- 如果
<n> = <max width>
, ,表/索引只能有 1 列 - 一般来说,表/索引只能有
<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个字符,但它们应该是远之间也很少,应使用作为可用于分析一个字段支持补充信息