第 48章インデックスアクセスメソッドのインタフェース定義

目次
48.1. インデックス用のカタログ項目
48.2. インデックスアクセスメソッド関数
48.3. インデックススキャン
48.4. インデックスのロック処理に関する検討
48.5. インデックス一意性検査
48.6. インデックスコスト推定関数

本章は、PostgreSQL の中核システムと、個々のインデックス種類を管理するインデックスアクセスメソッドとのインタフェースを定義します。 中核システムには、インデックスの仕様のみを把握しています。 したがって、追加コードを記述することで完全に新しいインデックス種類を開発することができます。

PostgreSQLのインデックスはすべて、技術的には補助的なインデックスとして知られるものです。 つまり、インデックスは対象となるテーブルファイルとは物理的に分かれています。 各インデックスは独自の物理的なリレーションとして格納され、また、pg_classカタログ内の項目として記述されます。 インデックスの内容は完全にそのインデックスアクセスメソッドの制御下にあります。 実際、すべてのインデックスアクセスメソッドは、通常の格納マネージャとバッファマネージャを使用してインデックスの内容にアクセスできるように、インデックスを標準サイズのページに分割します。 (既存のすべてのインデックスアクセスメソッドはさらに、項50.3で説明する標準ページレイアウトを使用し、すべて同じ書式をインデックスタプルヘッダに使用します。 しかし、これはアクセスメソッドに強制されていることではありません。)

インデックスは効率的にあるデータキー値を、インデックスの親テーブル内の行バージョン(タプル)のタプル識別子またはTIDsに関連付けます。 TIDは、ブロック番号、ブロック内の項目番号(項50.3を参照)から構成されます。 これは、特定の行バージョンをテーブルから取り出すのに十分な情報です。 MVCCでは1つの論理的な行に複数の現在のバージョンがあることを、インデックスが直接意識することはありません。 インデックスでは、各タプルは、独自にインデックス項目を持たなければならない独立したオブジェクトです。 したがって、行を更新すると、キーの値が変わっていなかってとしても、その行に対してまったく新しいインデックス項目が作成されます。 (バキューム実行によって)不要タプル自身が回収された時に、不要タプルに対するインデックス項目は回収されます。

48.1. インデックス用のカタログ項目

各インデックスメソッドは、pg_amシステムカタログ(項42.3を参照)内の行によって記述されます。 pg_am行の主な内容は、アクセスメソッドで提供されるインデックスアクセス関数を識別するpg_proc項目への参照です。 本章の後でこの関数用のAPIを定義します。 pg_am 行はさらに、複数列のインデックスをサポートするかなどといった、アクセスメソッドの固定属性をいくつか規定します。 現時点では、pg_am項目の作成や削除に関する特別な補助はありません。 新しいアクセスメソッドを作成することができる人間ならば、適切な行を挿入できる能力があると想定しています。

使い易くするために、インデックスアクセスメソッドはまた、pg_opclasspg_amopおよびpg_amproc内で定義される、複数の演算子クラスを持ちます。 これらの項目により、プランナは、このアクセスメソッドのインデックスがどのような問い合わせ条件に対して使用できるかを決定することができます。 演算子クラスについては、項32.14で説明します。 これは、本章を読む上で必要となる事柄です。

個々のインデックスは、インデックスを物理的なリレーションとして記述するpg_class項目と、インデックスの論理的な内容、つまり、インデックスが持つインデックス列の集合とその列の意味を、関連する演算子クラスで再現されたものとして表すpg_index項目とで定義されます。 インデックス列(キー値)は、背後のテーブルの単純な列、あるいは、テーブル行に対する式とすることができます。 通常、インデックスアクセスメソッドはインデックスキー値が何を表すかについて考慮しません。 (常に計算済みのキー値として扱われます。) しかし、pg_index内の演算子クラスの情報を深く考慮します。 この両方のカタログ項目は、インデックスに対するすべての操作に渡されるRelation データ構造の一部としてアクセスすることができます。

pg_amのフラグ列の中には、明確な意味を持たないものがあります。 amcanuniqueの必要条件は項48.5項48.4amconcurrentの必要条件で説明されています。 amcanmulticolフラグはアクセスメソッドが複数列に対するインデックスをサポートすることを表し、 amoptionalkeyは、インデックス可能な制限句が最初のインデックス列に指定されていないスキャンを許可することを表します。 amcanmulticolが偽の場合、amoptionalkeyは基本的に、アクセスメソッドが制限句なしで完全なインデックススキャンを許可するかどうかを表します。 複数列に対するインデックスをサポートするアクセスメソッドは、最初の列以降のすべてまたは一部の列に関する制限がなくてもスキャンをサポートしなければなりません。 しかし、最初のインデックス列にいくつかの制限を要求することは認められています。 これは、amoptionalkeyを偽に設定することで通知されます。 amindexnullsは、インデックス項目がNULLキー値に対して作成されることを表します。 ほとんどのインデックス可能な演算子は厳密で、NULL値の入力に対してTRUEを返すことができませんので、 NULLに対してインデックス項目を格納しないことは一見魅力的です。 これはインデックススキャンによって何も返しません。 しかし、最初のインデックス列に対する制限がないインデックススキャンでは、この引数は失敗します。 プランナがこうしたスキャンキーをまったく持たないインデックスを使用することを決定する可能性がありますので、実際これは、amoptionalkeyが真のインデックスはNULLインデックスを持たなければならないことを意味します。 関連する制限として、プランナはこれらの列を制限しない問い合わせでインデックスを使用することができると前提とするため、複数のインデックス列をサポートするインデックスアクセスメソッドは1番目の後の列でNULL値のインデックスをサポートしなければならないということがあります。 例えば、(a,b)に対するインデックスに、WHERE a = 4.という条件で問い合わせを行うことを考えてみます。 システムは、このインデックスを a = 4を持つ行をスキャンすることに使用できるものと仮定します。 これはもし、bがNULLの場合の行をインデックスが省略する場合は間違っています。 しかし、最初のインデックス列がNULLの場合に行を省略することは問題ありません (現在GiSTがこれを行っています)。 したがって、インデックスアクセスメソッドが任意のNULL値の組み合わせを含む、すべての行に対してインデックスを行う場合にのみ、amindexnullsを真にしなければなりません。