是否应向VARCHAR列添加任意长度限制?


35

根据PostgreSQL的文档VARCHARVARCHAR(n)和之间没有性能差异TEXT

我应该在名称地址列中添加任意长度限制吗?

编辑:不是欺骗:

我知道这种CHAR类型是过去的遗迹,我不仅对性能感兴趣,而且对诸如Erwin的其他利弊也很感兴趣。

Answers:


45

答案是否定的。如果可以避免,
请勿添加长度修饰符varchar。大多数时候,您实际上并不需要长度限制。仅text用于所有字符数据。varchar如果您需要与没有的RDBMS保持兼容,请设置为(无长度修饰符)text

性能几乎是相同的- text在罕见的情况下,快一点,你保存后,对长度的检查周期。

如果您实际上需要强制使用最大长度,请仍然使用text并为此添加检查约束

ALTER TABLE tbl ADD CONSTRAINT tbl_col_len CHECK (length(col) < 51);

您可以随时修改或删除这样的约束,而不必弄乱表定义和所有相关对象(视图,函数,外键等)。

使用长度修饰符,您只会遇到诸如此类此类此类的问题 ...

PostgreSQL 9.1引入了一个新功能来减轻这种痛苦。我在这里引用发行说明:

允许ALTER TABLE ... SET DATA TYPE在适当的情况下避免表重写(Noah Misch,Robert Haas)

例如,将varchar列转换为文本不再需要重写表。但是,增加varchar列的长度约束 仍然需要重写表。


我认为,如果仅仅是“不对真实的数据库添加任何限制”,那么答案会更好。我觉得很多答案都需要更正和进一步的信息,但这完全不合主题,并且会分散您的结论,我完全同意。
埃文·卡罗尔

是的,所有内容均基于9.1-6年前的Postgres版本。到现在有点尘土飞扬,但基本建议仍然不错。
Erwin Brandstetter

为每个文本列添加检查约束以进行健全性检查并确保客户端中的错误不会通过插入非常大的文本来耗尽数据库的所有磁盘空间,是个好主意还是坏主意?
代码

@Code:这是一个可行的选择。如果您有许多具有相同约束的列,请考虑domains。或者varchar(n)毕竟,为了简单起见-如果不利因素通常不会影响您。(如果要强制实际的最大长度,则该限制不是任意的。)
Erwin Brandstetter

12

如果您将长度限制视为一种检查约束,以确保您验证数据,则可以添加一个。事实上,你可能想使用长度定义,而是一个真正的检查约束代替,使改变的极限速度。

要更改(增加)长度限制,您需要运行,ALTER TABLE这可能需要很长时间才能完成(由于可能会重新写入表),在此期间需要排他的表锁定。

更改(即删除和重新创建)检查约束是一项非常简短的操作,仅需要读取表的数据,就不会更改任何行。因此,这将更快(这意味着排他表锁将被保留更短的时间)。

在操作过程中,a text,a varchar或一varchar(5000)列之间没有任何区别。


出于好奇,您为什么认为在捕获数据时无法在客户端应用程序上执行此长度检查?
PirateApp

4
@PirateApp:因为经常会有一个以上的应用程序或一些外部数据源(请考虑每晚批量导入)。几乎所有数据库(和数据)的寿命都比一个应用程序长。
a_horse_with_no_name

2

问题特别是是否在VARCHAR列中添加了任意长度限制

为此,答案就是“否”。没有什么可以像在支持varchar(max)或使用约定的劣等数据库中那样添加任意限制的理由varchar(255)。但是,如果规范解决了限制,我认为答案会变得更加复杂,尤其是在现代版本的PostgreSQL上。而且,为此,我倾向于YES

我认为,如果规范要求,则限制是明智的选择。特别是对于更合理的工作量。如果没有其他原因,则保留元数据。

从我这里的答案,可以看出CHAR与VARCHAR(Postgres)的索引性能,在这里我处理了元数据的值。

如果我发现规范中包含有意义的可变长度文本键,并且相信可以拥有恒定的最大长度,那么我也会使用varchar。但是,我想不出符合该标准的任何东西。


1

如果VARCHAR定期使用它们来存储非常大的字符串,则可能会出现性能差异,因为“长字符串会由系统自动压缩”和“非常长的值也存储在后台表中”。从理论上讲,这意味着对于非常长的字符串字段的大量请求将比对较短的字符串字段的请求慢。您可能永远不会遇到这个问题,因为名称和地址不会太长。

但是,根据您在数据库外部使用这些字符串的方式,您可能希望添加一个实际限制以防止滥用系统。例如,如果要在某处的表单上显示名称和地址,则可能无法在“名称”字段中显示整个文本段落,因此将“名称”列限制为500字符。


1
AFAIK在TOASTing varchar和text字段中没有区别。
dezso 2012年

VARCHARTEXTPostgres中的纯语法糖,在存储处理方面差异为零;您提到的压缩与后台表存储是基于列中数据的实际长度而不是列元数据完成的。TEXT列在内部存储为varlenaC结构(这是一个可变长度数组,前4个字节存储创建/更新时的长度),并且正是此结构根据其长度进行了优化。
Cowbert
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.