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

PostgreSQL: Difference between text and varchar (character varying)

text数据类型和character varying数据类型有什么区别?

根据文件

If character varying is used without length specifier, the type accepts strings of any size. The latter is a PostgreSQL extension.

In addition, PostgreSQL provides the text type, which stores strings of any length. Although the type text is not in the SQL standard, several other SQL database management systems have it as well.

那有什么区别呢?


没有区别,在引擎盖下面是所有的varlena(可变长度数组)。

从depesz查看本文:http://www.depesz.com/index.php/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/

几个亮点:

To sum it all up:

  • char(n) – takes too much space when dealing with values shorter than n (pads them to n), and can lead to subtle errors because of adding trailing
    spaces, plus it is problematic to change the limit
  • varchar(n) – it's problematic to change the limit in live environment (requires exclusive lock while altering table)
  • varchar – just like text
  • text – for me a winner – over (n) data types because it lacks their problems, and over varchar – because it has distinct name

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


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

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

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


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

并使用"纯SQL"基准(无任何外部脚本)

  • 使用任何带utf8的字符串生成器

  • 主要基准:

    2.1。插入

    2.2。选择比较和计数

  • 1
    2
    3
    4
    5
    6
    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;

    准备特定测试(示例)

    1
    2
    3
    4
    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) );

    执行基本测试:

    1
    2
    3
    INSERT INTO test  
       SELECT string_generator(20+(random()*(i%11))::INT)
       FROM generate_series(1, 99000) t(i);

    以及其他测试,

    1
    2
    3
    4
    5
    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性能!)根据CREATE TABLE中的with CHECK条款,如CHECK(char_length(x)<=10)等。插入/更新时性能损失可以忽略不计,您还可以控制范围和字符串结构
      例如CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')


    关于PostgreSQL手册

    There is no performance difference among these three types, apart from increased storage space when using the blank-padded type, and a few extra CPU cycles to check the length when storing into a length-constrained column. While character(n) has performance advantages in some other database systems, there is no such advantage in PostgreSQL; in fact character(n) is usually the slowest of the three because of its additional storage costs. In most situations text or character varying should be used instead.

    我通常用文字

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


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

    DR:如果在没有约束的情况下使用text类型,并且在这些列上有索引,则很可能在某些列中达到此限制,并且在尝试插入数据时出错,但在使用varchar(n)的情况下,可以防止出现错误。

    更多细节:这里的问题是,PostgreSQL在为text类型或varchar(n)创建索引时没有给出任何异常,其中n大于2712。但是,当试图插入压缩大小大于2712的记录时,它将给出错误。这意味着您可以插入由重复字符组成的100.000个字符串,因为它将被压缩到远远低于2712个字符,但由于压缩大小大于2712个字节,因此您可能无法插入某些4000个字符的字符串。使用varchar(n),其中n不超过2712,您可以安全地避免这些错误。


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

    1
    SELECT ' '::CHAR = ' '::VARCHAR, ' '::CHAR = ' '::text, ' '::VARCHAR = ' '::text

    返回true, false, true,而不是像您预期的那样返回true, true, true


    有点OT:如果您使用的是Rails,那么网页的标准格式可能会有所不同。对于数据输入表单,text框是可滚动的,但character varying框(rails string框是一行。显示视图的长度视需要而定。


    character varying(n)varchar(n)(两者相同)。值将被截断为n个字符,不会引发错误。character(n)char(n)(两者相同)。固定长度,并将与空白垫至长度结束。text—长度不限。

    例子:

    1
    2
    3
    4
    5
    6
    TABLE test:
       a CHARACTER(7)
       b VARCHAR(7)

    INSERT"ok   " TO a
    INSERT"ok   " TO b

    我们得到结果:

    1
    2
    3
    a        | (a)CHAR_LENGTH | b     | (b)CHAR_LENGTH
    ----------+----------------+-------+----------------
    "ok    "| 7              |"ok"  | 2