インデックススキャン

PostgreSQL 9.0.0文書
前のページ | 巻戻し | 第 51章インデックスアクセスメソッドのインタフェース定義 | 早送り | 次のページ

# 51.3. インデックススキャン

インデックススキャンでは、スキャンキーに一致するものと示したすべてのタプルのTIDを吐き出すことに関する責任をインデックスアクセスメソッドが持ちます。 アクセスメソッドには、実際のインデックスの親テーブルからのタプルの取り出しやタプルがスキャンの時間制限試験や他の条件を通過したかどうかの決定は含まれません。

スキャンキーは、`index_key` `operator` `constant`という形式の`WHERE`句の内部的表現です。 ここで、`index_key`は、インデックス列の1つで、`operator`はインデックス列に関連した演算子族のメンバの1つです。 インデックススキャンは、暗黙的にAND演算される0個以上のスキャンキーを持ちます。 返されるタプルは指定された条件を満たすものと想定されます。

アクセスメソッドはインデックスがある特定の問い合わせに対し非可逆、または再検査を要求するかどうかを報告することができます。 これは、インデックススキャンがスキャンキーを満たすすべての項目と、それに加えて、満たさない可能性のある項目を返すことを意味します。 中核システムのインデックススキャン機構はヒープタプルに対し、本当に選択されるべきかどうかを検証するためにその演算子をインデックス条件に再度適用します。 再検査オプションが指定されない場合、インデックススキャンは一致する項目の集合を返さなければなりません。

確実に、指定されたスキャンキーすべてに一致するもののみを全て正しく見つけ出すことは、完全にアクセスメソッドの責任であることに注意してください。 また、中核システムは、冗長かどうかや矛盾するかどうかを決定するための意味的な解析を行わず、単にインデックスキーと演算子族に一致する`WHERE`句をすべて渡します。 例えば、`WHERE x > 4 AND x > 14`があり、`x`がB-treeインデックス列であったとすると、これは、B-tree `amrescan`関数に任されて、最初のスキャンキーが冗長であり、無視することができることが認知されます。 `amrescan`における前処理の必要性は、インデックスアクセスメソッドがスキャンキーを"正規化"形式にする必要があるかどうかに依存します。

一部のアクセスメソッドは、他では行いませんが、十分に定義された順序でインデックス項目を返します。 ソートされた順序で項目が返される場合、アクセスメソッドは順序付きスキャンをサポートすることを示す`pg_am`.`amcanorder`を真に設定しなければなりません。 こうしたアクセスメソッドはすべて、その等価性演算子と順序付け演算子に関してB-Tree互換の戦略番号を使用しなければなりません。

`amgettuple`関数は`direction`引数を持ちます。 これは`ForwardScanDirection`（通常の場合）または`BackwardScanDirection`のいずれかを取ることができます。 `amrescan`後の最初の呼び出しが`BackwardScanDirection`を指定していた場合、一致したインデックス項目は通常の前から後ろという方向ではなく、後ろから前という方向でスキャンされます。 そのため、`amgettuple`は通常ならばインデックス内の最初に一致したタプルを返すところですが、最後に一致したタプルを返さなければなりません。 （これは順序付きスキャンをサポートするものと広告されたアクセスメソッドでのみ発生します。） 最初の呼び出しの後、`amgettuple`は、最も最近に返された項目からどちらの方向にスキャンを進めるかを準備しなければなりません。 （しかし`pg_am`.`amcanbackward`が偽であれば、引き続く全ての呼び出しは最初のものと同じ方向を持ちます。

順序付けされたスキャンを提供するアクセスメソッドはスキャン内位置の"記録"をサポートしなければならず、また、後でその記録された位置に戻ることをサポートしなければなりません。 同じ位置が複数回記録されるかもしれません。 しかし、スキャン内の1つの位置のみを記録する必要があります。 新しい`ammarkpos`呼び出しにより前回記録された位置は上書きされます。 順序付けされたスキャンをサポートしないアクセスメソッドであっても、`pg_am`内で記録用の関数と位置に戻るための関数を依然として提供しなければなりませんが、呼び出されたとしてもエラーを返すだけで十分です。

スキャン位置と記録された位置（もしあれば）の両方は、インデックス内の同時挿入や削除という観点における一貫性を保持しなければなりません。 スキャンが始まった時に存在していた場合、項目を見つけ出したスキャンが新しく挿入された項目を返さなかったとしても問題ありません。 このような場合のスキャンでは、再スキャンやバックアップによって、あたかも最初の時点で返されたものとして項目が返されます。 同様に、同時実行削除によってスキャンの結果に影響が出るかもしれません。 重要なことは、挿入や削除によって、その項目自体が挿入・削除されていない項目がスキャンで失われたり二重になったりすることが起こらないという点です。

`amgettuple`を使用する代わりに、`amgetbitmap`を使用して、一回の呼出しですべてのタプルを取り出してインデックススキャンを行うことができます。 これはアクセスメソッド内でのロック/ロック解除という過程を防ぐことができますので、`amgettuple`よりもかなり効率的です。 実際には、`amgetbitmap`は`amgettuple`呼び出しを繰り返すことと同じ効果を持つはずですが、物事を単純化するために複数の制限を加えています。 まず第一に、`amgetbitmap`は一回で全てのタプルを返し、スキャン位置の記録と位置戻しをサポートしません。 第二に、特定の順序付けをまったく持たないビットマップの中にタプルが返されます。 これは`amgetbitmap`が`direction`引数を取らない理由です。 最後に、`amgetbitmap`は返されたタプルに関し、項51.4に記載した意味でのロックを保証しません。

アクセスメソッドの内部実装がどちらか片方のAPIにそぐわない場合、`amgettuple`を実装せず`amgetbitmap`のみを実装、またはその逆も許されていることに注意してください。

前のページ | ホーム | 次のページ
インデックスアクセスメソッド関数 | 上に戻る | インデックスのロック処理に関する検討