CHARとVARCHAR(Postgres)のインデックスパフォーマンス


15

この答え(/programming/517579/strings-as-primary-keys-in-sql-database)で、1つの発言が目を引きました:

また、インデックスの比較を行うとき、CHARとVARCHARの間に非常に大きな違いがあることが多いことに留意してください

これはPostgresに適用されますか?

OracleのページCHARは多かれ少なかれエイリアスであるVARCHARと主張しているため、インデックスのパフォーマンスは同じですが、Postgresで決定的なものは何も見つかりませんでした。

回答:


24

CHAR そして VARCHARまったく同じのPostgres(とOracle)で実装されています。これらのデータ型を使用する場合、速度に違いはありません。

ただし、パフォーマンスに違いをもたらす可能性のある違いが1つあります。つまり、char列は常に定義された長さまで埋め込まれます。したがって、列をchar(100)1つとして定義し、varchar(100)それぞれに10文字しか保存しない場合、char(100)列は各値に100文字(保存した10文字と90スペース)を使用しますが、varchar列は10文字しか保存しません。

100文字と100文字を比較すると、10文字と10文字を比較するよりも遅くなります。ただし、SQLクエリでこの違いを実際に測定できるかどうかは疑問です。

10文字の長さで両方を宣言し、常に正確に格納する場合 10文字をする場合、まったく違いはありません(これはOracleとPostgresに当てはまります)

そのため、唯一の違いは、charデータ型に対して行われるパディングです。


また、インデックスの比較を行うとき、CHARとVARCHARの間に非常に大きな違いがあることが多いことに留意してください

上記の引用は、列の幅が広すぎる(つまり、パディングのためにスペースを無駄にしている)場合にのみ当てはまりcharます。char列の長さが常に完全に使用されている場合(パディングが発生しない場合)、上記の引用は間違っています(少なくともPostgresおよびOracleの場合)


私の観点から見ると、charデータ型には実際の単語はまったく使用されていません。varchar(またはtextPostgresで)使用するだけで、そのchar存在を忘れてください。


2
100文字と100文字を比較すると、10文字と10文字を比較するよりも遅くなります。ただし、SQLクエリでこの違いを実際に測定できるかどうかは疑問です。–並べ替えに加えてクエリが何をするかによって、違いが大きくなる場合があります。そのため、Postgres 9.5には新しい「短縮キー」機能があります:pgeoghegan.blogspot.de/2015/01/…– chirlu 16
1

6

私はa_horse_with_no_nameが言ったことすべてに同意します。そして、私は一般的にErwinのコメントアドバイスに同意します:

いいえ、charは劣っています(そして時代遅れです)。textとvarcharは(ほぼ)同じ動作をします。

メタデータ

1マイナーの例外を除いて、唯一の時間Iの使用はchar()、私はこれを言うためにメタデータが必要な場合であるしなければならないのx文字を持っています。char()入力が制限を超えている場合にのみ文句を言うことは知っていますが、CHECK制約のアンダーランから頻繁に保護します。例えば、

CREATE TABLE foo (
  x char(10) CHECK ( length(x) = 10 )
);
INSERT INTO foo VALUES (repeat('x', 9));

これにはいくつかの理由がありますが、

  1. char(x)スキーマローダーでは固定幅の列であると推測される場合があります。これにより、固定幅文字列用に最適化された言語に違いが生じる可能性があります。
  2. それは理にかなっており、簡単に施行される規則を確立します。この規則からコードを生成する言語でスキーマローダーを書くことができます。

私がこれを行う場所の例が必要です、

  1. 2文字の州の略語ですが、このリストは列挙できるため、通常はで行いますENUM
  2. 車両識別番号
  3. モデル番号(固定サイズ)

エラー発生時

一部の人々は、制限の両側のエラーメッセージの不一致に不快感を覚えるかもしれませんが、それは私を悩ませません

test=# INSERT INTO foo VALUES (repeat('x', 9));
ERROR:  new row for relation "foo" violates check constraint "foo_x_check"
DETAIL:  Failing row contains (xxxxxxxxx ).
test=# INSERT INTO foo VALUES (repeat('x', 11));
ERROR:  value too long for type character(10)

と対比 varchar

さらに、上記の提案は、ほぼ常にuseのtext規則に非常によく適合すると思います。あなたも質問しvarchar(n)ます。私はそれを決して使用しません。少なくとも、前回使っvarchar(n)たときのことは思い出せません。

  • 仕様に信頼できる静的な幅のフィールドがある場合はchar(n)
  • それ以外の場合、text効果的に使用しますvarchar(制限なし)

意味のある可変長テキストキーがあり、最大長が一定であると信頼している仕様を見つけた場合は、 varchar(n)ます。ただし、その基準に合うものは考えられません。

その他の注意事項

関連するQ&A:


1

Postgresql

sales_reporting_db=# create table x (y char(2));
CREATE TABLE
sales_reporting_db=# insert into x values ('Y');
INSERT 0 1
sales_reporting_db=# select '*' || y || '*' from x;
 ?column? 
----------
 *Y*

オラクル

SQL> create table x ( y char(2));

Table created.

SQL> insert into x values ('Y');

1 row created.

SQL> select '*' || y || '*' from x;

'*'|
----
*Y *

Postgresqlはスペースを埋め込みませんでした。


これはPostgresの単なる錯視です。試してくださいSELECT pg_column_size(y) FROM x;
dezso

-2

私はこれが最も便利であり、3行の速い説明が見つかりました:

CHAR(n)は、Postgresの中のテキスト対対VARCHAR(N)

  • 不明な長さのテキストを保存する場合は、TEXTデータ型を使用します。
  • 不明な長さのテキストを保存したいが、最大長がわかっている場合は、を使用しますVARCHAR(n)
  • 既知の正確な長さのテキストを保存する場合は、を使用しますCHAR(N)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.