PostgreSQL:text和varchar之间的区别(字符变化)

时间:2011-01-31 08:44:34

标签: string postgresql text types varchar

text数据类型与character varyingvarchar)数据类型之间有何区别?

根据the documentation

  

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

  

此外,PostgreSQL提供了文本类型,它存储任意长度的字符串。虽然类型文本不在SQL标准中,但其他几个SQL数据库管理系统也有它。

那有什么区别?

9 个答案:

答案 0 :(得分:623)

没有任何区别,因为它是全部varlenavariable length array)。

查看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 - 对我来说是胜利者 - over(n)数据类型,因为它没有问题,而且over varchar - 因为它有不同的名称
  •   

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

答案 1 :(得分:103)

正如文档中指出的“Character Types”一样,varchar(n)char(n)text都以相同的方式存储。唯一的区别是需要额外的周期来检查长度(如果有的话),以及char(n)需要填充所需的额外空间和时间。

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

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

答案 2 :(得分:44)

2016年更新基准(第9 + 5页)

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

  1. 使用任何带有UTF8的string_generator

  2. 主要基准:

    2.1。 INSERT

    2.2。选择比较和计算

  3. 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年更新(第10页)

    稍加编辑以添加2018的结果并强化推荐。

    2016年和2018年的结果

    我的结果,平均之后,在许多机器和许多测试中:全部相同
    (统计上较少的标准偏差)。

    建议

    • 使用text数据类型,以避免使用旧varchar(x),因为有时它不是标准,例如在CREATE FUNCTION条款中varchar(x) varchar(y)

    • 使用varchar中的CHECK子句表示限制(具有相同的CREATE TABLE性能!) CHECK(char_length(x)<=10)
      在INSERT / UPDATE中,如果性能损失可以忽略不计,您还可以控制范围和字符串结构。 CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')

答案 3 :(得分:29)

关于PostgreSQL手册

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

我通常使用文字

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

答案 4 :(得分:15)

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

<强> TL; DR: 如果您使用text类型而没有约束并且在这些列上有索引,则很可能您的某些列达到此限制并在尝试插入数据时出现错误但是使用varchar(n),您可以阻止它。

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

答案 5 :(得分:14)

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

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

正如您所料,返回true, false, true而不是true, true, true

答案 6 :(得分:4)

有点OT:如果你正在使用Rails,网页的标准格式可能会有所不同。对于数据输入表单text框是可滚动的,但character varying(Rails string)框是单行的。只要需要显示视图。

答案 7 :(得分:4)

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

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

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

答案 8 :(得分:0)

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

character(n)char(n) - (两者都相同)。固定长度,将填充空白直到长度的末端。

text - 无限长度。

示例:

Table test:
   a character(7)
   b varchar(7)

insert "ok    " to a
insert "ok    " to b

我们得到了结果:

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