回答:
違いはありません。内部的にはすべてです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 –テキストと同じ
- テキスト-私にとっては勝者 -(n)を超えるデータ型は問題がないため、varcharを超える-明確な名前があるため
この記事では詳細なテストを行って、4つのデータ型すべてに対する挿入と選択のパフォーマンスが類似していることを示しています。また、必要に応じて長さを制限する別の方法についても詳しく説明します。関数ベースの制約またはドメインは、長さ制約を即座に増やすという利点を提供します。また、文字列長の制約を減らすことはまれであることに基づいて、depeszは、通常、長さ制限の1つが最良の選択であると結論付けています。
「などの文字型のドキュメント・ポイントで」アウト、varchar(n)
、char(n)
、およびtext
すべて同じように保存されます。唯一の違いは、長さが指定されている場合は長さをチェックするために追加のサイクルが必要であり、にパディングが必要な場合は余分なスペースと時間が必要なことですchar(n)
。
ただし、1つの文字のみを格納する必要がある場合は、特殊なタイプを使用する方が若干パフォーマンスが向上します"char"
(二重引用符はそのままにしてください。これらはタイプ名の一部です)。フィールドへのアクセスが速くなり、長さを格納するオーバーヘッドがありません。
"char"
小文字のアルファベットから1,000,000個のランダムなテーブルを作成しました。頻度分布を取得するクエリ(select count(*), field ... group by field
)には約650ミリ秒かかりますが、text
フィールドを使用した同じデータでは約760 です。
"char"
は char
?? 最近のPostgreSQL 11以上で有効ですか?...はい: 「タイプ"char"
(引用符に注意)は、1バイトのストレージのみを使用するという点でchar(1)とは異なります。システムカタログでは、単純な列挙型として内部的に使用されます。」、ガイド/データ型文字。
「純粋なSQL」ベンチマークを使用する(外部スクリプトなし)
UTF8で任意のstring_generatorを使用する
主なベンチマーク:
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年の結果を追加し、推奨事項を強化するために少し編集します。
私の結果は、平均すると、多くのマシンと多くのテストですべて同じです
(統計的に標準偏差が少ない)。
使用text
データ型、
古い避けるvarchar(x)
時にはそれがで例えば、標準ではありませんので、 CREATE FUNCTION
句 varchar(x)
≠varchar(y)
。
egのvarchar
with CHECK
節で(同じパフォーマンスで!)制限を表現します。INSERT / UPDATEでのパフォーマンスの無視できる程度の損失であなたも範囲を制御し、文字列構造にすることができます たとえば、CREATE TABLE
CHECK(char_length(x)<=10)
CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')
"char"
はありません char
。ガイド/データ型文字は言う「タイプは、"char"
(引用符に注意してください)、それが唯一のストレージの1つのバイトを使用することでCHAR(1)と異なっている。これは内部としてシステムカタログで使用されている単純な列挙型。」。
PostgreSQLマニュアル
空白で埋められたタイプを使用する場合のストレージスペースの増加、および長さ制約のある列に格納する場合に長さをチェックするための追加のCPUサイクルがいくつかあることを除いて、これら3つのタイプの間にパフォーマンスの違いはありません。character(n)には他のいくつかのデータベースシステムではパフォーマンス上の利点がありますが、PostgreSQLにはそのような利点はありません。実際、追加のストレージコストのため、character(n)は通常3つの中で最も遅いです。ほとんどの場合、代わりにテキストまたは文字の変化を使用する必要があります。
私は通常テキストを使います
参照:http : //www.postgresql.org/docs/current/static/datatype-character.html
私の意見でvarchar(n)
は、独自の利点があります。はい、それらはすべて同じ基本型を使用しています。ただし、PostgreSQLのインデックスには、行あたり2712バイトのサイズ制限があることを指摘しておく必要があります。
TL; DR:制約なしでtext
タイプ
を使用し、これらの列にインデックスがある場合、一部の列でこの制限に達し、データを挿入しようとしたときにエラーが発生する可能性が非常に高いですが、を使用すると、それを防ぐことができます。varchar(n)
さらに詳細:ここでの問題は、PostgreSQLが2712より大きいtext
型またはvarchar(n)
whereのインデックスを作成するときに例外を与えないことn
です。ただし、2712より大きい圧縮サイズのレコードを挿入しようとすると、エラーが発生します。つまり、2712をはるかに下回って圧縮されるため、反復文字で構成される100.000文字の文字列を簡単に挿入できますが、圧縮サイズが2712バイトを超えるため、4000文字の文字列を挿入できない場合があります。使用するvarchar(n)
場所n
ではありませんあまりにも多くの 2712よりも大きい、あなたはこれらのエラーから安全です。
textとvarcharは、暗黙の型変換が異なります。私が気づいた最大の影響は、後続スペースの処理です。例えば ...
select ' '::char = ' '::varchar, ' '::char = ' '::text, ' '::varchar = ' '::text
期待どおりでtrue, false, true
はなくtrue, true, true
、戻ります。
http://www.sqlines.com/postgresql/datatypes/textからの良い説明:
TEXTとVARCHAR(n)の唯一の違いは、VARCHAR列の最大長を制限できることです。たとえば、VARCHAR(255)では、255文字を超える文字列を挿入できません。
TEXTとVARCHARはどちらも上限が1 GBであり、それらの間でパフォーマンスの違いはありません(PostgreSQLのドキュメントによると)。
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