web-dev-qa-db-ja.com

PostgreSQL:テキストとvarcharの違い(文字が変わる)

textデータ型とcharacter varyingvarchar)データ型の違いは何ですか?

によると{ ドキュメント

長さ指定子なしで文字可変が使用されている場合、タイプは任意のサイズの文字列を受け入れます。後者はPostgreSQLの拡張です。

そして

さらに、PostgreSQLは任意の長さの文字列を格納するテキスト型を提供します。タイプテキストは標準SQLにはありませんが、他のいくつかのSQLデータベース管理システムにもあります。

だから違いは何ですか?

521
Adam Matan

違いはありません、内部ではすべて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)データ型には問題がないため、varcharよりも - 重複した名前があるため

この記事では詳細なテストを行い、4つのデータ型すべてに対する挿入と選択のパフォーマンスが似ていることを示します。また、必要に応じて長さを制限するための代替方法について詳しく見ていきます。関数ベースの制約またはドメインは、長さの制約を即座に増やすという利点を提供します。また、ストリングの長さの制約を減らすことはまれであることに基づいて、dependentszはそれらのうちの1つが通常長さの制限に最適です。

619
Frank Heikens

ドキュメントの " 文字型 "が指摘するように、varchar(n)char(n)、およびtextはすべて同じ方法で格納されます。唯一の違いは、長さが指定されている場合は長さをチェックするために余分なサイクルが必要であり、char(n)にパディングが必要な場合は余分なスペースと時間が必要なことです。

ただし、1文字だけを格納する必要がある場合は、特殊な型"char"を使用することでパフォーマンスがわずかに向上します(二重引用符を使用します - それらは型名の一部です)。フィールドへのアクセスが速くなり、長さを格納するためのオーバーヘッドがなくなります。

私はちょうど小文字のアルファベットから選ばれた1,000,000個のランダムな"char"のテーブルを作りました。頻度分布(select count(*), field ... group by field)を取得するためのクエリは、textフィールドを使用した同じデータに対する約760に対して、約650ミリ秒かかります。

103
George

2016年のベンチマークの更新(pg9.5 +)

そして「純粋なSQL」ベンチマークを使用する(外部スクリプトなしで)

  1. uTF8で任意のstring_generatorを使用する

  2. 主なベンチマーク:

    2.1。インサート

    2.2。 SELECT比較とカウント


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年の結果

私の結果は、平均して、多くのマシンと多くのテストで: すべて同じ
(統計的に標準偏差よりも小さい)。

勧告

  • textデータ型を使用します。
    時にはそれが標準ではないので、古いvarchar(x)を避ける。 CREATE FUNCTION句のvarchar(x) - ≠ varchar(y)にあります。

  • CREATE TABLEvarchar節を使用して、(同じCHECKパフォーマンスで)制限を明示する
    例えば。 CHECK(char_length(x)<=10)
    INSERT/UPDATEのパフォーマンスがごくわずかに低下するだけで、範囲とストリング構造を制御することもできます。
    例えば。 CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')

44
Peter Krauss

PostgreSQLマニュアル上

これら3つのタイプの間には、ブランク埋め込みタイプを使用するときの記憶スペースの増加、および長さ制限のある列に保管するときの長さをチェックするための余分なCPUサイクルがいくつかあるだけです。 character(n)は他のデータベースシステムではパフォーマンス上の利点がありますが、PostgreSQLではそのような利点はありません。実際、文字(n)は追加のストレージコストのため、通常3つのうちで最も遅いです。ほとんどの場合、代わりにテキストや文字を使用するべきです。

私は通常テキストを使います

参照先: http://www.postgresql.org/docs/current/static/datatype-character.html

29
user5507680

私の意見では、varchar(n)にはそれ自身の利点があります。はい、それらはすべて同じ基本型とすべてを使用しています。ただし、PostgreSQLのインデックスのサイズ制限は、1行あたり 2712バイト です。

TL; DR: text type 制約なしを使用していて、これらのカラムにインデックスがある場合、いくつかのカラムでこの制限に達するとエラーが発生する可能性があります。データを挿入しますが、varchar(n)を使用すると、それを防ぐことができます。

もう少し詳しく: /ここでの問題は、PostgreSQLがtext型またはvarchar(n)のインデックスを作成するときに例外を出さないことです。ただし、nが2712より大きい場合、エラーが発生します。 2712を挿入しようとしています。それはあなたがそれが2712よりはるかに下で圧縮されるので繰り返し文字で容易に構成される100.000文字の文字列を挿入することができることを意味しますが、圧縮サイズが2712バイトより大きいので4000文字で文字列を挿入できないかもしれません。 nが2712よりも大きくない{too too}であるvarchar(n)を使用すると、これらのエラーから安全です。

14
sotn

textとvarcharは、暗黙的に型変換が異なります。私が気付いた最大の影響は、末尾のスペースの処理です。例えば ​​...

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

ご想像のとおり、true, false, trueではなくtrue, true, trueを返します。

14
bpd

ややOT:もしあなたがRailsを使っているなら、Webページの標準フォーマットは異なるかもしれません。データ入力フォームの場合、textボックスはスクロール可能ですが、character varying(Rails string)ボックスは1行です。表示ビューは必要なだけ長くなります。

4
Greg

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
0
ofir_aghai