text
数据类型和character varying
(varchar
)数据类型有什么区别?根据文档说明,如果使用character varying而没有指定长度,该类型接受任何大小的字符串,后者是PostgreSQL的扩展。此外,PostgreSQL还提供了text类型,它存储任意长度的字符串。虽然text类型不属于SQL标准,但其他几个SQL数据库管理系统也具有该类型。那么这两种数据类型有什么区别呢?text
数据类型和character varying
(varchar
)数据类型有什么区别?根据文档说明,如果使用character varying而没有指定长度,该类型接受任何大小的字符串,后者是PostgreSQL的扩展。此外,PostgreSQL还提供了text类型,它存储任意长度的字符串。虽然text类型不属于SQL标准,但其他几个SQL数据库管理系统也具有该类型。那么这两种数据类型有什么区别呢?在技术实现上,这些都是相同的,底层使用的是varlena
(可变长度数组)。
可以查看Depesz的这篇文章:http://www.depesz.com/index.php/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/
以下是一些要点:
综上所述:
- char(n) - 当处理短于
n
的值时需要太多的空间(将它们填充到n
),并且由于添加尾随空格可能导致微妙的错误,更改限制也会出现问题- varchar(n) - 在实时环境中更改限制有问题(需要独占锁定以修改表)
- varchar - 就像text
- text - 对我来说是最好的选择 - 因为它没有上述数据类型的问题,并且比varchar更具有区分性的名称
该文章进行了详细测试,以显示4种数据类型的插入和选择性能相似。它还详细研究了在需要时限制长度的替代方法。基于函数的约束或域提供即时增加长度约束的优势,并且基于字符串长度约束的缩小是罕见的,Depesz得出结论:它们通常是限制长度的最佳选择之一。
varchar(n)
、char(n)
和text
都是以相同的方式存储的。唯一的区别在于,如果给定长度,则需要额外的循环来检查长度,并且如果需要填充char(n)
,则需要额外的空间和时间。"char"
(保留双引号——它们是类型名称的一部分)会稍微提高性能。您可以更快地访问字段,并且没有存储长度的开销。"char"
的表。查询频率分布(select count(*), field ... group by field
)需要约650毫秒,而在相同的数据上使用text
字段需要约760毫秒。"char"
不是char
吗?在PostgreSQL 11+的今天仍然有效吗?是的:*"类型"char"
(注意引号)与char(1)
不同,它只使用一个字节的存储空间。它在系统目录中内部用作简单枚举类型。"*guide/datatype-character。 - Peter Krauss并使用“纯SQL”基准测试(无任何外部脚本)
使用任何UTF8字符串生成器
主要基准测试:
2.1. 插入
2.2. 选择比较和计数
CREATE FUNCTION string_generator(int DEFAULT 20,int DEFAULT 10) RETURNS text AS $f$
SELECT array_to_string( array_agg(
substring(md5(random()::text),1,$1)||chr( 9824 + (random()*10)::int )
), ' ' ) as s
FROM generate_series(1, $2) i(x);
$f$ LANGUAGE SQL IMMUTABLE;
准备具体测试(示例)
DROP TABLE IF EXISTS test;
-- CREATE TABLE test ( f varchar(500));
-- CREATE TABLE test ( f text);
CREATE TABLE test ( f text CHECK(char_length(f)<=500) );
进行基本测试:
INSERT INTO test
SELECT string_generator(20+(random()*(i%11))::int)
FROM generate_series(1, 99000) t(i);
还有其他的测试,
CREATE INDEX q on test (f);
SELECT count(*) FROM (
SELECT substring(f,1,1) || f FROM test WHERE f<'a0' ORDER BY 1 LIMIT 80000
) t;
我在许多机器和许多测试后得出的结果经平均后都是相同的(统计学上小于标准偏差)。
使用text
数据类型,
避免使用旧的varchar(x)
,因为有时它不是标准的,例如在CREATE FUNCTION
子句中varchar(x)
≠varchar(y)
。
通过在CREATE TABLE
中使用CHECK
子句来表达限制(具有相同的varchar
性能!)
例如:CHECK(char_length(x)<=10)
。
通过在 INSERT/UPDATE 中忽略可忽略的性能损失,您也可以控制范围和字符串结构
例如:CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')
在PostgreSQL手册中
这三种类型之间没有性能差异,除了使用填充空格类型时增加的存储空间以及在存储到长度受限列时检查长度所需的一些额外CPU周期。虽然在其他一些数据库系统中,character(n)具有性能优势,但在PostgreSQL中并没有这样的优势;事实上,由于其额外的存储成本,character(n)通常是三种类型中最慢的。在大多数情况下,应该使用text或character varying。
我通常使用text
参考资料:http://www.postgresql.org/docs/current/static/datatype-character.html
在我看来,varchar(n)
有其自身的优点。是的,它们都使用相同的底层类型等等。但是,应该指出的是,在PostgreSQL中,索引在每行中具有2712字节的大小限制。
TL;DR:
如果您使用text
类型没有约束条件并对这些列进行索引,很可能会命中某些列的限制,并且在尝试插入数据时出现错误,但是如果使用varchar(n)
,则可以避免这种情况。
更多细节:问题在于,当为text
类型或varchar(n)
创建索引时,PostgreSQL不会提供任何异常,其中n
大于2712。但是,当尝试插入压缩大小大于2712的记录时,它将给出错误。这意味着您可以轻松地插入由重复字符组成的100,000个字符的字符串,因为它将被压缩到远低于2712以下,但是您可能无法插入一些具有4000个字符的字符串,因为压缩后的大小大于2712字节。使用varchar(n)
,其中n
不是远大于2712,您就可以避免出现这些错误。
text和varchar具有不同的隐式类型转换。我注意到的最大影响是对尾随空格的处理。例如...
select ' '::char = ' '::varchar, ' '::char = ' '::text, ' '::varchar = ' '::text
返回的结果是true, false, true
而不是你可能期望的true, true, true
。
=
运算符不仅比较值,还会进行一些转换来找到值的公共类型。这是各种语言中非常常见的行为,并且所使用的转换方式也因语言而异。例如在 JavaScript 中,你可以看到 [0 == '0.0', 0 == '0', '0.0' == '0']
-> [true, true, false]
。 - Arsen7以下是http://www.sqlines.com/postgresql/datatypes/text提供的良好解释:
TEXT和VARCHAR(n)之间唯一的区别在于,您可以限制VARCHAR列的最大长度,例如,VARCHAR(255)不允许插入超过255个字符的字符串。
TEXT和VARCHAR的上限均为1 Gb,在它们之间没有性能差异(根据PostgreSQL文档)。
有点离题:如果你在使用Rails,那么网页的标准格式可能会有所不同。对于数据输入表单,text
框是可以滚动的,但是character varying
(Rails string
)框只有一行。展示视图则根据需要长短不一。
text
绝不能被认为是“优于 varchar 的胜者”,相反,你应该深入考虑要存储什么类型的数据,然后才允许用户输入字符串。绝不能采用“前端处理”这种策略,这是非常不可接受和糟糕的开发实践。现在看到很多开发人员都这样做,真的很惊讶。 - José L. Patiño