2

検討:

create table tab (foo text not null);
create index tab_ix_foo on tab(foo);

select * from tab where foo like 'pre%';

Postgres はその検索を行うためにインデックスを使用しません。collat​​ion を使用する場合"POSIX"、Postgres はインデックスを使用します: http://sqlfiddle.com/#!12/ed1cc/1

collat​​ion を使用する場合"en_US"、Postgres は順次スキャンを使用します: http://sqlfiddle.com/#!12/efb18/1

違いはなぜですか?

4

1 に答える 1

4

C(つまり)以外のロケールを使用する場合は、 opclassを使用してテキスト検索のインデックスとプレフィックスPOSIXを作成する必要があります。Operator クラスインデックス タイプに関するドキュメントを参照してください。そのドキュメントページよりも優れたリファレンスがあると確信していますが、現時点では見つけられないようです。LIKE~text_pattern_ops

インデックスに使用するように SQLFiddle を変更するtext_pattern_opsと、en_USインデックスを使用できることがわかります

create index tab_ix_foo on tab using btree (foo collate "en_US" text_pattern_ops);
--                                                              ^^^^^^^^^^^^^^^^

9.2 以降でこのオプションを使用している場合は、照合ごとに異なるインデックスを作成する必要がある可能性が非常に高くなります。これはCOLLATE、定義上、照合順序が異なると、文字列の順序が異なり、したがって b ツリーの編成が異なることを意味するためです。テストですでにこれを行っているようです。

また、データが小さすぎて、インデックスの使用が特に有用でない可能性もあります。より有用な量のデータでテストしてみてください。

Collat​​ion supportのドキュメントと同様に、この投稿は役立つ場合があります。


異なる照合に同じ B ツリー インデックスを使用できない理由については、B ツリーには安定した一貫した順序付けが必要であると考えてください。

regress=> SELECT ' Bill''s' > ('bills' COLLATE "POSIX");
 ?column? 
----------
 f
(1 row)

regress=> SELECT ' Bill''s' > ('bills' COLLATE "en_US");
 ?column? 
----------
 t
(1 row)

ご覧のとおり、照合によって並べ替え順序が変更されます。それが、ほとんど定義上、照合が行うことです。異なる照合に同じインデックスを使用しようとすることは、異なる関数に同じ関数インデックスを使用しようとするようなものです。まったく意味がありません。

于 2013-03-24T11:16:06.467 に答える