使用数据类型“文本”存储字符串有啥缺点吗?
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)
char
或 character
只是 character(1)
的缩写,所以都一样。内部名称是bpchar
(代表“空白填充字符”)。该类型仅用于与旧代码和标准兼容。现在已经没什么意义了,浪费内存,很可能会造成麻烦:
您可以使用带有长度修饰符的varchar(n)
(character varying(n)
的别名)。但是 typically indicates a misunderstanding 是从其他 RDBMS 继承而来的,它可能是性能的局部最优值。在 Postgres 中,长度修饰符 varchar(255)
(255)
没有特殊含义,很少有意义。
以后尝试更改varchar(n)
的长度修饰符时,旧版本会导致各种问题。大多数这些问题在现代 Postgres 中都得到了缓解,但没有长度说明符的 text
或 varchar
(character varying
的别名)(以及 CHECK
constraint 代替)从未遇到任何这些问题。
CHECK
约束与依赖于列类型的依赖视图、函数、FK 约束等一样快且不太可能导致问题。它可以做的不仅仅是强制最大字符长度——任何你可以放入布尔表达式的东西。见:
最后,还有"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
)
CHAR
和 VARCHAR
数据类型只是为此添加了长度检查,并且(在 CHAR
的情况下)具有不同的空格填充语义。
您可以安全地使用TEXT
,只要上述任何内容对您的逻辑都不重要。
【讨论】:
【参考方案3】:从您链接到的页面:
“这三种类型之间没有性能差异,除了 从使用空白填充类型时增加的存储空间,以及 几个额外的 CPU 周期来检查存储到 长度受限的列。虽然字符(n)有性能 在其他一些数据库系统中的优势,没有这样的优势 在 PostgreSQL 中;事实上 character(n) 通常是最慢的 三是因为其额外的存储成本。在大多数情况下,文本 或应改用字符变化。”
在 Postgres 中使用 text
数据类型似乎没有任何缺点。
但是,您应该考虑是否真的要允许将大量文本存储在数据库中。将其保留为 varchar
但具有更高的限制可以防止您无意中在数据库中存储大量数据。
【讨论】:
那么会使用CHECK
约束吗?
@Vérace 从v9.2 开始,我更喜欢varchar(n)
而不是text
,因为它允许我增加长度而无需重新检查。无论您是否增加字符长度,更改检查约束都会强制重新检查。该检查使用 AccessExclusiveLock,防止读取,使其不适合生产数据库。以上是关于使用数据类型“文本”存储字符串有啥缺点吗?的主要内容,如果未能解决你的问题,请参考以下文章