web-dev-qa-db-ja.com

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

この回答( https://stackoverflow.com/questions/517579/strings-as-primary-keys-in-sql-database )では、1つのコメントが私の目を引きました:

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

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

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

16
LetMeSOThat4U

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

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

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

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

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


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

上記の引用はonly trueであり、char列の幅が広すぎると定義されている(つまり、パディングのためにスペースを浪費している)場合に限ります。 char列の長さが常に完全に使用されている(つまり、パディングが発生していない)場合、上記の引用は正しくありません(少なくともPostgresおよびOracleの場合)。


私の観点からは、charデータ型は実際にはWordで使用されません。 varchar(またはPostgresではtext)を使用し、charが存在することを忘れてください。

24

私はすべてに同意します said by a_horse_with_no_name、そして私は一般的にアーウィンのコメントアドバイスに同意します:

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

メタデータ

1つのマイナーな例外を除いて、onlyを使用する時間char()は、メタデータでこれを言いたいときです[〜#〜] must [〜#〜]には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と対比

さらに、上記の提案はalmostは常にtextを使用するという慣例に非常に適していると思います。あなたはvarchar(n)についても尋ねます。 私はそれを使用しません。少なくとも、最後にvarchar(n)を使用したときのことは思い出せません。

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

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

その他の注意事項

  • charここでは、_"char"_ と混同しないでください。これは1バイトタイプであり、確かなパフォーマンスとスペース節約の利点があります。

関連するQ&A:

6
Evan Carroll

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はスペースを埋めませんでした。

1
user939857