PostgreSQL:textとvarcharの違い(文字は異なります)


620

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

ドキュメントによると

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

そして

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

違いは何ですか?

回答:


746

違いはありません。内部的にはすべてです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つが最良の選択であると結論付けています。


58
@axiopisty素晴らしい記事です。「記事がダウンした場合に備えて、いくつかの抜粋を取り入れてもらえますか?」私は記事の内容/結論を簡単に要約しようとしました。これであなたの心配を和らげるのに十分だと思います。
jpmc26 2014

34
@axiopisty、厳密に言えば、最初の回答は「内部ではすべてvarlenaです」と言っていました。これは、この回答をリンクのみの回答と区別するのに役立つ情報です。
ブルーノ

24
制限のない文字列で覚えておくべきことの1つは、乱用の可能性を開くことです。ユーザーが任意のサイズの姓を持つことを許可すると、誰かが姓フィールドに大量の情報を格納する可能性があります。で、物品のredditの開発について、彼らは「すべての制限を置く」ように助言を与えます。
Mark Hildreth、2015年

7
@MarkHildreth良い点ですが、一般に、このような制約は最近のアプリケーションでさらに実施されているため、UI(および違反/再試行の試み)はUIでスムーズに処理できます。誰かがまだデータベースでこの種のことをしたい場合は、制約を使用できます。「TEXTと制約を使用してVARCHARよりも柔軟なフィールドを作成する例」を含むblog.jonanin.com/2013/11/20/postgresql-char-varcharを参照してください。
イーサン

4
@Ethan blog.jonanin.com/2013/11/20/postgresql-char-varchar->これはダウンしていますが、archive.is / 6xhA5にあります。
MrR 2018年

115

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

ただし、1つの文字のみを格納する必要がある場合は、特殊なタイプを使用する方が若干パフォーマンスが向上します"char"(二重引用符はそのままにしてください。これらはタイプ名の一部です)。フィールドへのアクセスが速くなり、長さを格納するオーバーヘッドがありません。

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


18
技術的には、引用符は型名の一部ではありません。charキーワードと区別するために必要です。
Jasen

31
技術的には正しい@Jasen ...もちろん、これは最良の種類の正しいものです
JohannesH

データ型"char"char?? 最近のPostgreSQL 11以上で有効ですか?...はい: 「タイプ"char"(引用符に注意)は、1バイトのストレージのみを使用するという点でchar(1)とは異なります。システムカタログでは、単純な列挙型として内部的に使用されます。」ガイド/データ型文字
Peter Krauss、

64

2016年のベンチマークの更新(9.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 FUNCTIONvarchar(x)varchar(y)

  • egのvarcharwith CHECK節で(同じパフォーマンスで!)制限を表現します。INSERT / UPDATEでのパフォーマンスの無視できる程度の損失であなたも範囲を制御し、文字列構造にすることができます たとえば、CREATE TABLE
    CHECK(char_length(x)<=10)

    CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')


それで、テキストの代わりにすべての列をvarcharにしたよりも問題ではないのですか?5文字と、確かではない255 -私はいくつかはわずか4であっても長さを指定しなかった
トレンチ

1
@trenchはい、それは問題ではありません
FuriousFolder

1
かっこいい、安全のためにやり直し、とにかくすべてをテキストにしました。それはうまくいき、とにかく何百万もの履歴レコードを素早く追加するのは非常に簡単でした。

@trenchとreader:唯一の例外は、より高速なデータ型であり、現在のPostgreSQL 11以降でもそうで"char"はありません charガイド/データ型文字は言う「タイプは、"char"(引用符に注意してください)、それが唯一のストレージの1つのバイトを使用することでCHAR(1)と異なっている。これは内部としてシステムカタログで使用されている単純な列挙型。」
Peter Krauss、2018

3
2019年もpg11で引き続き有効:text> varchar(n)> text_check> char(n)
Olivier Refalo

37

PostgreSQLマニュアル

空白で埋められたタイプを使用する場合のストレージスペースの増加、および長さ制約のある列に格納する場合に長さをチェックするための追加のCPUサイクルがいくつかあることを除いて、これら3つのタイプの間にパフォーマンスの違いはありません。character(n)には他のいくつかのデータベースシステムではパフォーマンス上の利点がありますが、PostgreSQLにはそのような利点はありません。実際、追加のストレージコストのため、character(n)は通常3つの中で最も遅いです。ほとんどの場合、代わりにテキストまたは文字の変化を使用する必要があります。

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

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


23

私の意見で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よりも大きい、あなたはこれらのエラーから安全です。


後でテキストのインデックス作成を試みる際のpostgresエラーは、varchar((n)なしのバージョン)でのみ機能します。ただし、埋め込まれたpostgresでのみテストされています。
arntg 2018年

2
参照先:stackoverflow.com/questions/39965834/…PostgreSQL Wikiへのリンクがあるwiki: wiki.postgresql.org/wiki/…の 最大行サイズは400GBであり、行あたりの2712バイトの制限が間違っているようです。データベースの最大サイズ?無制限(32 TBデータベースが存在)テーブルの最大サイズ?行の最大サイズは32 TBですか?フィールドの最大サイズは400 GB?1 GBテーブルの最大行数?無制限
ビルワージントン

@BillWorthingtonただし、投稿した数値は、インデックスの配置を考慮していません。2712バイトは、btreeの最大制限についてです。これは実装の詳細であるため、ドキュメントで見つけることができません。ただし、「postgresqlインデックスの行サイズがインデックスの最大2712を超えている」などを検索することで、自分で簡単にテストしたり、ググったりできます。
2018

私はPostgeSQLを初めて使用するため、専門家ではありません。ニュース記事をテーブルの列に格納するプロジェクトに取り組んでいます。私が使用するのはテキスト列タイプのようです。2712バイトの合計行サイズは、Oracleと同じレベルに近いと想定されるデータベースには小さすぎると思われます。大きなテキストフィールドのインデックス作成について言及していることを正しく理解していますか?あなたに挑戦したり議論したりするのではなく、本当の限界を理解しようとするだけです。インデックスが含まれていない場合、行の制限はwikiのように400GBになりますか?迅速な対応ありがとうございます。
Bill Worthington

1
@BillWorthington全文検索について調査する必要があります。チェックこのリンクなど
sotn

18

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

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

期待どおりでtrue, false, trueはなくtrue, true, true、戻ります。


これはどのようにして可能ですか?a = bおよびa = cの場合、b = cです。
Lucas Silva

4

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


2

http://www.sqlines.com/postgresql/datatypes/textからの良い説明:

TEXTとVARCHAR(n)の唯一の違いは、VARCHAR列の最大長を制限できることです。たとえば、VARCHAR(255)では、255文字を超える文字列を挿入できません。

TEXTとVARCHARはどちらも上限が1 GBであり、それらの間でパフォーマンスの違いはありません(PostgreSQLのドキュメントによると)。


-1

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

5
MySQLは値が列サイズを超えたときにデータを黙って切り捨てますが、PostgreSQLは「値が長すぎて型の文字vary(n)にならない」エラーを発生させません。
gsiems
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.