使用数据类型“text”存储字符串有什么不足之处吗?
使用数据类型“text”存储字符串有什么不足之处吗?
根据PostgreSQL文档,他们支持3种字符数据类型:
character varying(n), varchar(n) 可变长度,有限制
character(n), char(n) 固定长度,填充空格
text 可变长度,无限制
在我的应用程序中,我遇到了一些不愉快的情况,插入/更新查询失败,因为要插入的所需文本超过了varchar(n)
或char(n)
的限制。
对于这种情况,将这些列的数据类型更改为text
就足够了。
我的问题是:
- 如果我们将每个字符存储列的数据类型统一更改为
text
,在性能/内存方面有什么不利之处吗? - 如果数据类型为
text
的列每次存储10个或更少的字符,我应该选择text
还是varchar(10)
? - 如果我选择
text
,有什么不利之处?
在Postgres中使用数据类型"text"存储字符串是否存在任何缺点?
根据你提供的页面内容,似乎在Postgres中使用"text"数据类型没有任何缺点。然而,你应该考虑是否真的希望允许大量文本存储在数据库中。将其保留为具有更高限制的"varchar"类型可以防止在数据库中意外存储大量数据。
另外,你可以考虑使用"CHECK"约束来解决这个问题。从v9.2版本开始,我更喜欢使用"varchar(n)"而不是"text",因为它允许我在不重新检查的情况下增加长度。修改检查约束会强制重新检查,无论你是否增加字符长度。这个检查使用AccessExclusiveLock,阻止读取操作,对于生产数据库来说并不理想。
使用数据类型"text"存储字符串有什么缺点吗?
这个问题的出现原因是,使用数据类型"text"存储字符串时,可能会出现以下问题:
1. 数据类型"text"没有长度检查,因此无法限制字符串的长度。
2. 数据类型"text"在存储时不会进行空格填充,可能会导致字符串的长度不一致。
为了解决这些问题,可以采取以下方法:
1. 如果需要限制字符串的长度,可以使用"CHAR"或"VARCHAR"数据类型,它们在内部使用相同的结构体"varlena",并通过添加长度检查来限制字符串的长度。
2. 如果字符串的长度不重要,可以安全地使用数据类型"text",因为它不会进行长度检查和空格填充。
使用数据类型"text"存储字符串的缺点是无法限制字符串的长度,并且不会进行空格填充。为了解决这些问题,可以使用"CHAR"或"VARCHAR"数据类型进行长度检查,或者在不需要限制字符串长度和空格填充的情况下使用数据类型"text"。
使用数据类型"text"存储字符串有什么缺点?
在性能/内存方面,使用"text"没有任何缺点,相反,它是最佳选择。其他类型有更多或更少相关的缺点。"text"在Postgres类型系统中是字符串类型中的“首选”类型,这可能会影响函数或运算符类型的解析。
特别地,除非你知道自己在做什么,否则永远不要使用 char(n)(别名为 character(n))。char或character只是character(1)的简称,所以它们是一样的。内部名称是bpchar(代表"空白填充字符")。这种类型只是为了与旧代码和标准兼容而存在。现在几乎没有什么意义,浪费内存,而且很可能会引起麻烦。
你可以使用带有长度修饰符的varchar(n)(别名为character varying(n))。但是varchar(255)通常意味着从其他RDBMS中带过来的误解,它可能是性能的局部最优解。在Postgres中,长度修饰符(255)没有特殊含义,很少有意义。
旧版本在尝试后期更改varchar(n)的长度修饰符时会导致各种问题。现代Postgres已经缓解了大部分问题,但是没有长度限定符的text或varchar(别名为character varying)(并使用CHECK约束)从来没有出现过这些问题。
CHECK约束与速度相当,并且不太可能引起依赖于列类型的视图、函数、外键约束等的问题。它不仅可以强制最大字符长度,还可以执行任何布尔表达式。参见:
- Change PostgreSQL columns used in views
最后,还有"char"(带双引号):一个用作廉价内部枚举类型的1字节数据类型,表示单个ASCII字母。
在Postgres中,我很少使用除了"text"以外的任何字符数据类型。
从PG 9.2开始,可以增加/删除varchar(n)约束而不需要对表进行重写。如果你不想直接添加SQL约束,使用像Django这样的ORM更容易,它会将它们映射到varchar(n)。除了上述在9.2中解决的问题之外,还有其他原因更喜欢"text"而不是varchar(n)吗?
: 很好,重要的更新。Postgres 9.2带来了重大改进,消除了更改长度修饰符时对表进行重写的需要。但是,带有CHECK约束的text仍然更加灵活,特别是在9.1引入的NOT VALID约束和9.2的更新之后。这里有一个相关的博客,有很好的解释:blog.endpoint.com/2012/11/...
使用char_length()比length()稍微好一些吗?
: 两者完全相同。唯一的区别是,length()有其他数据类型的变体。
显然,我的思维不知何故将bit_length()函数和length(string bytea, encoding name)混合在一起,都合并成了一个不存在的函数。