使用数据类型“文本”存储字符串有啥缺点吗?

Posted

技术标签:

【中文标题】使用数据类型“文本”存储字符串有啥缺点吗?【英文标题】:Any downsides of using data type "text" for storing strings?使用数据类型“文本”存储字符串有什么缺点吗? 【发布时间】:2013-12-18 01:52:37 【问题描述】:

根据PostgreSQL Documentation,它们支持3种数据类型的字符数据:

character varying(n), varchar(n)  variable-length with limit
character(n), char(n)             fixed-length, blank padded
text                              variable unlimited length

在我的应用程序中,我遇到了一些令人不快的情况,其中插入/更新查询失败,因为要插入的所需文本超出了 varchar(n)char(n) 限制。

对于此类情况,将此类列的数据类型更改为text 就足够了。

我的问题是:

如果我们将每个字符存储列的数据类型泛化并更改为text,在性能/内存方面是否有任何不利之处? 如果数据类型为text 的列每次存储10 个或更少的字符,我应该选择text 还是varchar(10)? 如果我选择text 有什么缺点?

【问题讨论】:

另见***.com/q/23988406/398670 【参考方案1】:

一般来说,使用text 在性能/内存方面没有缺点。相反:text 是最优的。其他类型或多或少有相关的缺点。 text 字面意思是 Postgres 类型系统中的 "preferred" type among string types,它会影响函数或运算符类型的解析。

尤其是never use char(n)character(n) 的别名),除非您知道自己在做什么。 charcharacter 只是 character(1) 的缩写,所以都一样。内部名称是bpchar(代表“空白填充字符”)。该类型仅用于与旧代码和标准兼容。现在已经没什么意义了,浪费内存,很可能会造成麻烦:

Compare varchar with char String field length in Postgres SQL

您可以使用带有长度修饰符的varchar(n)character varying(n) 的别名)。但是varchar(255) typically indicates a misunderstanding 是从其他 RDBMS 继承而来的,它可能是性能的局部最优值。在 Postgres 中,长度修饰符 (255) 没有特殊含义,很少有意义。

Should I add an arbitrary length limit to VARCHAR columns?

以后尝试更改varchar(n) 的长度修饰符时,旧版本会导致各种问题。大多数这些问题在现代 Postgres 中都得到了缓解,但没有长度说明符的 textvarcharcharacter varying 的别名)(以及 CHECK constraint 代替)从未遇到任何这些问题。

CHECK 约束与依赖于列类型的依赖视图、函数、FK 约束等一样快且不太可能导致问题。它可以做的不仅仅是强制最大字符长度——任何你可以放入布尔表达式的东西。见:

Change PostgreSQL columns used in views

最后,还有"char"(带双引号):用于单个 ASCII 字母的 1 字节数据类型,用作廉价的内部枚举类型。

除了text 在 Postgres 中,我很少使用任何其他字符数据。

【讨论】:

从 PG 9.2 开始,varchar(n) 约束可以在不重写表的情况下增加/删除。如果您不想直接添加 SQL 约束,那么使用像 Django 这样的 ORM 会更容易,它通过将长度约束字段映射到 varchar(n) 来处理它们。除了 9.2 中解决的上述问题之外,还有其他理由更喜欢 text 而不是 varchar(n)? postgresql.org/docs/9.2/static/release-9-2.html @buffer:好点,重要的更新。 Postgres 9.2 带来了重大改进,在更改长度说明符时不再需要重写表。但是带有CHECK 约束的text 仍然更加通用,在9.1 中引入NOT VALID constraints 并在9.2 中更新更是如此。这是一个相关的博客,写得很好:blog.endpoint.com/2012/11/… @ErwinBrandstetter 不会使用 char_length()length() 稍微好一点? @dezso:两者的作用完全相同。唯一的区别是:length() 有其他数据类型的变体。 @ErwinBrandstetter 显然,我的思绪不知何故混入了bit_length() 函数和length(string bytea, encoding name ) —— 都变成了一个不存在的函数。【参考方案2】:

你提到的所有数据类型都使用相同的内部表示(比较有名的struct varlena

CHARVARCHAR 数据类型只是为此添加了长度检查,并且(在 CHAR 的情况下)具有不同的空格填充语义。

您可以安全地使用TEXT,只要上述任何内容对您的逻辑都不重要。

【讨论】:

【参考方案3】:

从您链接到的页面:

“这三种类型之间没有性能差异,除了 从使用空白填充类型时增加的存储空间,以及 几个额外的 CPU 周期来检查存储到 长度受限的列。虽然字符(n)有性能 在其他一些数据库系统中的优势,没有这样的优势 在 PostgreSQL 中;事实上 character(n) 通常是最慢的 三是因为其额外的存储成本。在大多数情况下,文本 或应改用字符变化。”

在 Postgres 中使用 text 数据类型似乎没有任何缺点。

但是,您应该考虑是否真的要允许将大量文本存储在数据库中。将其保留为 varchar 但具有更高的限制可以防止您无意中在数据库中存储大量数据。

【讨论】:

那么会使用CHECK 约束吗? @Vérace 从v9.2 开始,我更喜欢varchar(n) 而不是text,因为它允许我增加长度而无需重新检查。无论您是否增加字符长度,更改检查约束都会强制重新检查。该检查使用 AccessExclusiveLock,防止读取,使其不适合生产数据库。

以上是关于使用数据类型“文本”存储字符串有啥缺点吗?的主要内容,如果未能解决你的问题,请参考以下文章

将存储过程与 Dapper 一起使用有啥缺点吗?

oracle数据库中,存储过程中 %rowtype 类型的用法有啥限制吗?

带有外部模板的自定义类型 fmt 格式化程序,有啥缺点吗?

位掩码的整数和位(n)数据类型之间有啥区别吗?

将 html 存储在数据库中以供使用有啥缺点?

Redis 数据类型分析 字符串 哈希 列表 集合 有序集合 优缺点 分析 注意事项 存储结构