文本数据类型和字符变化(varchar)数据类型之间的区别是什么?
根据文档
如果使用不带长度说明符的字符变化,则该类型接受任何大小的字符串。后者是PostgreSQL的扩展。
and
此外,PostgreSQL还提供了文本类型,用于存储任意长度的字符串。尽管类型text不在SQL标准中,但其他几个SQL数据库管理系统也具有它。
那么有什么不同呢?
文本数据类型和字符变化(varchar)数据类型之间的区别是什么?
根据文档
如果使用不带长度说明符的字符变化,则该类型接受任何大小的字符串。后者是PostgreSQL的扩展。
and
此外,PostgreSQL还提供了文本类型,用于存储任意长度的字符串。尽管类型text不在SQL标准中,但其他几个SQL数据库管理系统也具有它。
那么有什么不同呢?
当前回答
在我看来,varchar(n)有它自己的优点。是的,它们都使用相同的底层类型等等。但是,应该指出的是,PostgreSQL中的索引有其每行2712字节的大小限制。
TL;博士: 如果您使用无约束的文本类型,并且在这些列上有索引,则很可能在某些列上达到此限制,并在尝试插入数据时出错,但使用varchar(n)可以防止这种情况。
Some more details: The problem here is that PostgreSQL doesn't give any exceptions when creating indexes for text type or varchar(n) where n is greater than 2712. However, it will give error when a record with compressed size of greater than 2712 is tried to be inserted. It means that you can insert 100.000 character of string which is composed by repetitive characters easily because it will be compressed far below 2712 but you may not be able to insert some string with 4000 characters because the compressed size is greater than 2712 bytes. Using varchar(n) where n is not too much greater than 2712, you're safe from these errors.
其他回答
没有区别,在引子里都是可变长度数组。
查看本文来自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 -对我来说是胜过(n)数据类型的赢家,因为它没有数据类型的问题,胜过varchar -因为它有独特的名称
本文进行了详细的测试,以证明所有4种数据类型的插入和选择的性能是相似的。它还详细介绍了在需要时限制长度的其他方法。基于函数的约束或域提供了立即增加长度约束的优势,并且基于减少字符串长度约束的情况很少,depesz得出结论,它们中的一个通常是长度限制的最佳选择。
正如文档中的“字符类型”所指出的,varchar(n)、char(n)和text都是以相同的方式存储的。唯一的区别是需要额外的循环来检查长度,如果给定了一个,如果需要填充char(n),则需要额外的空间和时间。
然而,当您只需要存储单个字符时,使用特殊类型“char”会有轻微的性能优势(保留双引号-它们是类型名称的一部分)。您可以更快地访问字段,并且没有存储长度的开销。
我刚刚创建了一个包含1,000,000个从小写字母中随机选择的“字符”的表。查询频率分布(select count(*), field…按字段分组)大约需要650毫秒,而使用文本字段的相同数据大约需要760毫秒。
来自http://www.sqlines.com/postgresql/datatypes/text:的一个很好的解释
TEXT和VARCHAR(n)之间的唯一区别是您可以限制 VARCHAR列的最大长度,例如VARCHAR(255) 不允许插入长度超过255个字符的字符串。 TEXT和VARCHAR的上限都是1gb,但是没有 它们之间的性能差异(根据PostgreSQL 文档)。
(这个答案是Wiki,你可以编辑-请改正和改进!)
更新2016年基准(pg9.5+)
使用“纯SQL”基准测试(不需要任何外部脚本)
使用UTF8的任何string_generator 主要指标:
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;
... 并使用EXPLAIN ANALYZE。
2018年再次更新(pg10)
小小的编辑增加了2018年的结果,并加强了建议。
2016年和2018年的结果
我的结果,在许多机器和许多测试中,经过平均后:都是一样的(统计上小于标准偏差)。
建议
使用文本数据类型,避免旧的varchar(x),因为有时它不是一个标准,例如在CREATE FUNCTION子句中varchar(x)≠varchar(y)。 用CREATE表中的CHECK子句表达限制(具有相同的varchar性能!),例如CHECK(char_length(x)<=10)。在INSERT/UPDATE中可以忽略不计的性能损失,您还可以控制范围和字符串结构,例如CHECK(char_length(x)>5 and char_length(x)<=20 and x LIKE 'Hello%')
我浪费了太多的时间,因为使用varchar而不是文本的PostgreSQL数组。
数组操作符不能处理字符串列。详情请参阅以下链接:(https://github.com/rails/rails/issues/13127)和(http://adamsanderson.github.io/railsconf_2013/?full#10)。