PostgreSQLインデックス-2



インターフェース



最初の部分では、アクセス方法が自分に関する情報を提供する必要があるという事実について話しました。 このインターフェースの仕組みを見てみましょう。



プロパティ



アクセス方法のすべてのプロパティは、pg_amテーブルに表示されます(am-アクセス方法)。 この表から、使用可能なメソッドのリストを取得できます。



postgres=# select amname from pg_am;

amname

--------

btree

hash

gist

gin

spgist

brin

(6 rows)







シーケンシャルスキャンはアクセス方法に当然起因すると考えられますが、歴史的にはこのリストにはないことが判明しています。



PostgreSQL 9.5以降では、各プロパティはpg_amテーブルの個別のフィールドで表されていました。 バージョン9.6以降、プロパティは特別な機能によってポーリングされ、いくつかのレベルに分割されます。





アクセス方法とインデックスレベルの分離は、将来を見据えて行われます。現在、同じアクセス方法に基づいて作成されたすべてのインデックスは、常に同じプロパティを持ちます。





アクセス方法のプロパティには、次の4つが含まれます(例としてbtreeを使用)。



postgres=# select a.amname, p.name, pg_indexam_has_property(a.oid,p.name)

from pg_am a,

unnest(array['can_order','can_unique','can_multi_col','can_exclude']) p(name)

where a.amname = 'btree' order by a.amname;

amname | name | pg_indexam_has_property

--------+---------------+-------------------------

btree | can_order | t

btree | can_unique | t

btree | can_multi_col | t

btree | can_exclude | t

(4 rows)











インデックスに関連するプロパティ(たとえば、いくつかの既存のものを取得します):



postgres=# select p.name, pg_index_has_property('t_a_idx'::regclass,p.name)

from unnest(array['clusterable','index_scan','bitmap_scan','backward_scan']) p(name);

name | pg_index_has_property

---------------+-----------------------

clusterable | t

index_scan | t

bitmap_scan | t

backward_scan | t

(4 rows)











最後に、列のプロパティ:



postgres=# select p.name, pg_index_column_has_property('t_a_idx'::regclass,1,p.name)

from unnest(array['asc','desc','nulls_first','nulls_last','orderable','distance_orderable','returnable','search_array','search_nulls']) p(name);

name | pg_index_column_has_property

--------------------+------------------------------

asc | t

desc | f

nulls_first | f

nulls_last | t

orderable | t

distance_orderable | f

returnable | t

search_array | t

search_nulls | t

(9 rows)










すでに詳細に説明したプロパティの一部。 現在、一部のプロパティは1つのメソッドによってのみ実装されています。 この特定の方法について話すとき、そのような可能性を考慮します。



演算子のクラスとファミリー



「スキル」のセットに加えて、アクセス方法が機能するデータの種類とオペレーターを知る必要があります。 このため、PostgreSQLには演算子クラス演算子族の概念があります。



演算子クラスには、インデックスが特定のデータ型で動作するための最小限の演算子(および場合によっては補助関数)のセットが含まれます。



クラスは常に演算子のファミリーの一部です。 同時に、複数のクラスが同じセマンティクスを持っている場合、1つの共通のファミリに含まれることがあります。 たとえば、integer_opsファミリには、int8_ops、int4_ops、およびint2_opsのクラスが含まれます。これらは、意味が同じである異なるタイプのbigint、integer、およびsmallintに対応しています。



postgres=# select opfname, opcname, opcintype::regtype

from pg_opclass opc, pg_opfamily opf

where opf.opfname = 'integer_ops'

and opc.opcfamily = opf.oid

and opf.opfmethod = (select oid from pg_am where amname = 'btree');

opfname | opcname | opcintype

-------------+----------+-----------

integer_ops | int2_ops | smallint

integer_ops | int4_ops | integer

integer_ops | int8_ops | bigint

(3 rows)







別の例:datetime_opsファミリには、日付を処理するための演算子クラスが含まれています(時間なしと時間付きの両方):



postgres=# select opfname, opcname, opcintype::regtype

from pg_opclass opc, pg_opfamily opf

where opf.opfname = 'datetime_ops'

and opc.opcfamily = opf.oid

and opf.opfmethod = (select oid from pg_am where amname = 'btree');

opfname | opcname | opcintype

--------------+-----------------+-----------------------------

datetime_ops | date_ops | date

datetime_ops | timestamptz_ops | timestamp with time zone

datetime_ops | timestamp_ops | timestamp without time zone

(3 rows)







ファミリには、異なるタイプの値を比較するための追加の演算子も含まれる場合があります。 ファミリーでグループ化することにより、スケジューラーは、異なるタイプの値を持つ述部のインデックスを使用できます。 ファミリには、他の補助機能も含まれる場合があります。



ほとんどの場合、演算子族とクラスは何も知る必要はありません。 通常、インデックスを作成するだけで、デフォルトでいくつかのクラスの演算子を使用します。



ただし、演​​算子クラスを明示的に指定できます。 これが必要な場合の簡単な例:C以外の並べ替え規則を持つデータベースでは、通常のテキストフィールドインデックスはLIKE操作をサポートしません。



postgres=# show lc_collate;

lc_collate

-------------

en_US.UTF-8

(1 row)

postgres=# explain (costs off) select * from t where b like 'A%';

QUERY PLAN

-----------------------------

Seq Scan on t

Filter: (b ~~ 'A%'::text)

(2 rows)







この制限は、演算子クラスtext_pattern_opsを使用してインデックスを作成することで克服できます(プランの条件がどのように変更されたかに注意してください)。



postgres=# create index on t(b text_pattern_ops);

CREATE INDEX

postgres=# explain (costs off) select * from t where b like 'A%';

QUERY PLAN

----------------------------------------------------------------

Bitmap Heap Scan on t

Filter: (b ~~ 'A%'::text)

-> Bitmap Index Scan on t_b_idx1

Index Cond: ((b ~>=~ 'A'::text) AND (b ~<~ 'B'::text))

(4 rows)







システムカタログ



このパートを締めくくるために、演算子のクラスとファミリーに直接関連するシステムカタログ表の小さな図を示します。







もちろん、これらの表はすべて詳細に説明されています。



システムカタログを使用すると、ドキュメントを見なくても多くの質問に対する答えを見つけることができます。 たとえば、これまたはそのアクセス方法で使用できるデータの種類は何ですか?



postgres=# select opcname, opcintype::regtype

from pg_opclass

where opcmethod = (select oid from pg_am where amname = 'btree')

order by opcintype::regtype::text;

opcname | opcintype

---------------------+-----------------------------

abstime_ops | abstime

array_ops | anyarray

enum_ops | anyenum

...







クラスにはどの演算子が含まれていますか(したがって、そのような演算子を含む条件によるアクセスにインデックスを使用できますか)?



postgres=# select amop.amopopr::regoperator

from pg_opclass opc, pg_opfamily opf, pg_am am, pg_amop amop

where opc.opcname = 'array_ops'

and opf.oid = opc.opcfamily

and am.oid = opf.opfmethod

and amop.amopfamily = opc.opcfamily

and am.amname = 'btree'

and amop.amoplefttype = opc.opcintype;

amopopr

-----------------------

<(anyarray,anyarray)

<=(anyarray,anyarray)

=(anyarray,anyarray)

>=(anyarray,anyarray)

>(anyarray,anyarray)

(5 rows)







継続する



All Articles