文本和varchar之间的区别(字符变化)

text数据类型和character varyingvarchar)数据类型之间有什么区别?

根据留档

如果在没有长度说明符的情况下使用字符变化,则该类型接受任何大小的字符串。后者是PostgreSQL扩展。

此外,PostgreSQL提供了text类型,用于存储任何长度的字符串。尽管text类型不在SQL标准中,但其他SQL数据库管理系统也有它。

那么有什么区别呢?

458271 次浏览

没有区别,引擎盖下都是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-就像文本一样
  • 文字-对我来说是赢家-over(n)数据类型,因为它没有问题,over varchar-因为它有不同的名称

本文进行了详细的测试,以表明所有4种数据类型的插入和选择的性能相似。它还详细研究了在需要时约束长度的替代方法。基于函数的约束或域提供了即时增加长度约束的优势,并且基于减少字符串长度约束的情况很少,Depesz得出结论,其中之一通常是长度限制的最佳选择。

正如留档中的“字符类型”所指出的,varchar(n)char(n)text都以相同的方式存储。唯一的区别是需要额外的周期来检查长度(如果给定一个),如果需要填充,则需要额外的空间和时间。

但是,当您只需要存储单个字符时,使用特殊类型"char"(保留双引号-它们是类型名称的一部分)会有轻微的性能优势。您可以更快地访问该字段,并且没有存储长度的开销。

我刚刚从小写字母中选择了一个包含1,000,000个随机"char"的表。获取频率分布(select count(*), field ... group by field)的查询大约需要650毫秒,而使用text字段的相同数据大约需要760毫秒。

关于PostgreSQL手册

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

我通常使用文本

参考文献:http://www.postgresql.org/docs/current/static/datatype-character.html

(这个答案是一个Wiki,您可以编辑-请纠正和改进!)

2016年基准更新(pg9.5+)

使用“纯SQL”基准测试(没有任何外部脚本)

  1. 使用UTF8的任何string_generator

  2. 主要基准:

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 sFROM 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 testSELECT 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年的结果

我的结果,平均后,在许多机器和许多测试:都一样
(统计小于均方差)。

建议

  • 使用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%')

有些OT:如果您使用的是Rails,网页的标准格式可能会有所不同。对于数据输入表单,text框是可滚动的,但character varying(Railsstring)框是单行的。显示视图的长度取决于需要。

text和varchar有不同的隐式类型转换。我注意到的最大影响是处理尾随空格。例如…

select ' '::char = ' '::varchar, ' '::char = ' '::text, ' '::varchar = ' '::text

返回true, false, true,而不是你所期望的true, true, true

character varying(n)varchar(n)-(两者相同). value将被截断为n个字符而不会引发错误。

character(n)char(n)-(两者相同)。固定长度,并将填充空白直到长度结束。

text-无限长度。

示例:

Table test:a character(7)b varchar(7)
insert "ok    " to ainsert "ok    " to b

我们得到了结果:

a        | (a)char_length | b     | (b)char_length----------+----------------+-------+----------------"ok     "| 7              | "ok"  | 2

在我看来,varchar(n)有它自己的优势。是的,它们都使用相同的底层类型等等。但是,应该指出的是,PostgreSQL中的索引的大小限制为每行2712字节

太长别读:如果您使用text类型没有限制并在这些列上有索引,则很可能您的某些列达到此限制并在尝试插入数据时出错,但使用varchar(n),您可以阻止它。

更多细节:这里的问题是PostgreSQL在为text类型或varchar(n)创建索引时没有给出任何例外,其中n大于2712。然而,当尝试插入压缩大小大于2712的记录时,它会出错。这意味着您可以轻松插入100.000个由重复字符组成的字符串,因为它将被压缩到远低于2712的位置,但您可能无法插入一些具有4000个字符的字符串,因为压缩大小大于2712字节。使用varchar(n),其中n不是太多大于2712,您可以避免这些错误。

http://www.sqlines.com/postgresql/datatypes/text的一个很好的解释:

TEXT和VARCHAR(n)之间的唯一区别是您可以限制VARCHAR列的最大长度,例如,VARCHAR(255)不允许插入长度超过255个字符的字符串。

TEXT和VARCHAR的上限都为1 Gb,并且没有它们之间的性能差异(根据PostgreSQL留档

我浪费了太多时间,因为PostgreSQL数组使用varchar而不是text。

PostgreSQL数组运算符不适用于字符串列。有关更多详细信息,请参阅这些链接:(https://github.com/rails/rails/issues/13127)和(http://adamsanderson.github.io/railsconf_2013/?full#10)。

如果您仅使用TEXT类型,则在使用AWS数据库迁移服务时可能会遇到问题:

使用大对象(LOB),但目标LOB列不可为空

由于它们未知,有时尺寸很大,大型对象(LOB)需要更多的处理和资源而不是标准对象。帮助调整包含LOB,AWS DMS提供以下选项

如果您只坚持PostgreSQL的所有内容,那么您可能没问题。但是,如果您要通过ODBC或DMS等外部工具与您的数据库进行交互,您应该考虑对所有内容使用而不是使用TEXT。

区别在于传统和现代。

传统上,您需要指定每个表格列的宽度。如果您指定的宽度太多,则会浪费昂贵的存储空间,但如果您指定的宽度太少,则某些数据将无法容纳。然后您将调整列的大小,并且必须更改许多连接的软件,修复引入的错误,这都是非常麻烦的。

现代系统允许具有动态存储分配的无限字符串存储,因此附带的大字符串可以很好地存储,而不会浪费小数据项的存储。

虽然许多编程语言都采用了无限大小的“字符串”数据类型,如C#、javascript、java等,但像Oracle这样的数据库却没有。

现在PostgreSQL支持“text”,很多程序员仍然习惯使用VARCHAR(N),原因如下:是的,text与VARCHAR相同,只是使用VARCHAR可以添加限制N,因此VARCHAR更灵活。

你也可以推理,既然我们可以用#1简化我们的生活,我们为什么还要使用#0呢?

在我最近几年与Oracle的合作中,我很少使用CHAR(N)或VARCHAR(N)。因为Oracle没有无限的字符串类型,所以我在大多数字符串列中使用VARCHAR(2000),其中2000在某个时候是VARCHAR的最大值,并且在所有实际用途中与“无限”没有太大区别。

现在我正在使用PostgreSQL,我认为TEXT是真正的进步。不再强调CHAR类型的VAR特性。不再强调让我们使用不带N的VARCHAR。此外,与VARCHAR相比,键入TEXT可以节省3次击键。

年轻的同事现在长大了,甚至不知道过去没有无限的字符串。就像在大多数项目中一样,他们不必了解汇编编程。