バージョンごとのドキュメント一覧

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

<title>Index Scanning</title>

In an index scan, the index access method is responsible for regurgitating the TIDs of all the tuples it has been told about that match the <firstterm>scan keys</firstterm>. The access method is <emphasis>not</emphasis> involved in actually fetching those tuples from the index's parent table, nor in determining whether they pass the scan's visibility test or other conditions. インデックススキャンでは、スキャンキーに一致するものと示したすべてのタプルのTIDを繰り返すことに関する責任をインデックスアクセスメソッドが持ちます。 アクセスメソッドには、実際のインデックスの親テーブルからのタプルの取り出しやタプルがスキャンの可視性テストや他の条件を通過したかどうかの決定は含まれません

A scan key is the internal representation of a <literal>WHERE</literal> clause of the form <replaceable>index_key</replaceable> <replaceable>operator</replaceable> <replaceable>constant</replaceable>, where the index key is one of the columns of the index and the operator is one of the members of the operator family associated with that index column. An index scan has zero or more scan keys, which are implicitly ANDed &mdash; the returned tuples are expected to satisfy all the indicated conditions. スキャンキーは、index_key operator constantという形式のWHERE句の内部的表現です。 ここで、index_keyは、インデックス列の1つで、operatorはインデックス列に関連した演算子族のメンバの1つです。 インデックススキャンは、暗黙的にAND演算される0個以上のスキャンキーを持ちます。 返されるタプルは指定された条件を満たすものと想定されます。

The access method can report that the index is <firstterm>lossy</firstterm>, or requires rechecks, for a particular query. This implies that the index scan will return all the entries that pass the scan key, plus possibly additional entries that do not. The core system's index-scan machinery will then apply the index conditions again to the heap tuple to verify whether or not it really should be selected. If the recheck option is not specified, the index scan must return exactly the set of matching entries. アクセスメソッドはインデックスがある特定の問い合わせに対し非可逆、または再検査を要求するかどうかを報告することができます。 これは、インデックススキャンがスキャンキーを満たすすべての項目と、それに加えて、満たさない可能性のある項目を返すことを意味します。 コアシステムのインデックススキャン機構はヒープタプルに対し、本当に選択されるべきかどうかを検証するためにその演算子をインデックス条件に再度適用します。 再検査オプションが指定されない場合、インデックススキャンは一致する項目の集合を返さなければなりません。

Note that it is entirely up to the access method to ensure that it correctly finds all and only the entries passing all the given scan keys. Also, the core system will simply hand off all the <literal>WHERE</literal> clauses that match the index keys and operator families, without any semantic analysis to determine whether they are redundant or contradictory. As an example, given <literal>WHERE x &gt; 4 AND x &gt; 14</literal> where <literal>x</literal> is a b-tree indexed column, it is left to the b-tree <function>amrescan</function> function to realize that the first scan key is redundant and can be discarded. The extent of preprocessing needed during <function>amrescan</function> will depend on the extent to which the index access method needs to reduce the scan keys to a <quote>normalized</quote> form. 確実に、指定されたスキャンキーすべてに一致するもののみをすべて正しく見つけ出すことは、完全にアクセスメソッドの責任であることに注意してください。 また、コアシステムは、冗長かどうかや矛盾するかどうかを決定するための意味的な解析を行わず、単にインデックスキーと演算子族に一致するWHERE句をすべて渡します。 例えば、WHERE x > 4 AND x > 14があり、xがB-treeインデックス列であったとすると、これは、B-tree amrescan関数に任されて、最初のスキャンキーが冗長であり、無視できることが認知されます。 amrescanにおける前処理の必要性は、インデックスアクセスメソッドがスキャンキーを正規化形式にする必要があるかどうかに依存します。

Some access methods return index entries in a well-defined order, others do not. There are actually two different ways that an access method can support sorted output: 一部のアクセスメソッドは、他では行いませんが、十分に定義された順序でインデックス項目を返します。 アクセスメソッドが出力の順序付けをサポートできるようにする方法は、実質2種類存在します。

The <function>amgettuple</function> function has a <literal>direction</literal> argument, which can be either <literal>ForwardScanDirection</literal> (the normal case) or <literal>BackwardScanDirection</literal>. If the first call after <function>amrescan</function> specifies <literal>BackwardScanDirection</literal>, then the set of matching index entries is to be scanned back-to-front rather than in the normal front-to-back direction, so <function>amgettuple</function> must return the last matching tuple in the index, rather than the first one as it normally would. (This will only occur for access methods that set <structfield>amcanorder</structfield> to true.) After the first call, <function>amgettuple</function> must be prepared to advance the scan in either direction from the most recently returned entry. (But if <structfield>amcanbackward</structfield> is false, all subsequent calls will have the same direction as the first one.) amgettuple関数はdirection引数を持ちます。 これはForwardScanDirection(通常の場合)またはBackwardScanDirectionのいずれかを取ることができます。 amrescan後の最初の呼び出しがBackwardScanDirectionを指定していた場合、一致したインデックス項目は通常の前から後ろという方向ではなく、後ろから前という方向でスキャンされます。 そのため、amgettupleは通常ならばインデックス内の最初に一致したタプルを返すところですが、最後に一致したタプルを返さなければなりません。 (これはamcanorderが真に設定されたアクセスメソッドでのみ発生します。) 最初の呼び出しの後、amgettupleは、最も最近に返された項目からどちらの方向にスキャンを進めるかを準備しなければなりません。 (しかしamcanbackwardが偽であれば、引き続くすべての呼び出しは最初のものと同じ方向を持ちます。)

Access methods that support ordered scans must support <quote>marking</quote> a position in a scan and later returning to the marked position. The same position might be restored multiple times. However, only one position need be remembered per scan; a new <function>ammarkpos</function> call overrides the previously marked position. An access method that does not support ordered scans need not provide <function>ammarkpos</function> and <function>amrestrpos</function> functions in <structname>IndexAmRoutine</structname>; set those pointers to NULL instead. 順序付けされたスキャンを提供するアクセスメソッドはスキャン内位置の記録をサポートしなければならず、また、後でその記録された位置に戻ることをサポートしなければなりません。 同じ位置が複数回記録されるかもしれません。 しかし、スキャン内の1つの位置のみを記録する必要があります。 新しいammarkpos呼び出しにより前回記録された位置は上書きされます。 順序付けされたスキャンをサポートしないアクセスメソッドはIndexAmRoutineammarkpos関数およびamrestrpos関数を提供する必要はないので、これらのポインタをNULLにセットしてください。

Both the scan position and the mark position (if any) must be maintained consistently in the face of concurrent insertions or deletions in the index. It is OK if a freshly-inserted entry is not returned by a scan that would have found the entry if it had existed when the scan started, or for the scan to return such an entry upon rescanning or backing up even though it had not been returned the first time through. Similarly, a concurrent delete might or might not be reflected in the results of a scan. What is important is that insertions or deletions not cause the scan to miss or multiply return entries that were not themselves being inserted or deleted. スキャン位置と記録された位置(もしあれば)の両方は、インデックス内の同時挿入や削除という観点における一貫性を保持しなければなりません。 スキャンが始まった時に存在していた場合、項目を見つけ出したスキャンが新しく挿入された項目を返さなかったとしても問題ありません。 このような場合のスキャンでは、再スキャンやバックアップによって、あたかも最初の時点で返されたものとして項目が返されます。 同様に、同時実行削除によってスキャンの結果に影響が出るかもしれません。 重要なことは、挿入や削除によって、その項目自体が挿入・削除されていない項目がスキャンで失われたり二重になったりすることが起こらないという点です。

If the index stores the original indexed data values (and not some lossy representation of them), it is useful to support <link linkend="indexes-index-only-scans">index-only scans</link>, in which the index returns the actual data not just the TID of the heap tuple. This will only avoid I/O if the visibility map shows that the TID is on an all-visible page; else the heap tuple must be visited anyway to check MVCC visibility. But that is no concern of the access method's. インデックスが設定された列値がインデックスに格納されている(かつ、損失のある表現ではない)場合、ヒープタプルのTIDではなくインデックスに格納された実際のデータを返すインデックスオンリースキャンをサポートするのに有用です。 これは、可視性マップによってTIDが全可視のページ上にあると判断できる場合にI/Oを避けるだけのことです。 判断できない場合はMVCCを確認するためにヒープタプルにアクセスしなくてはなりません。 しかしその動作はアクセスメソッドでは考慮されていません。

Instead of using <function>amgettuple</function>, an index scan can be done with <function>amgetbitmap</function> to fetch all tuples in one call. This can be noticeably more efficient than <function>amgettuple</function> because it allows avoiding lock/unlock cycles within the access method. In principle <function>amgetbitmap</function> should have the same effects as repeated <function>amgettuple</function> calls, but we impose several restrictions to simplify matters. First of all, <function>amgetbitmap</function> returns all tuples at once and marking or restoring scan positions isn't supported. Secondly, the tuples are returned in a bitmap which doesn't have any specific ordering, which is why <function>amgetbitmap</function> doesn't take a <literal>direction</literal> argument. (Ordering operators will never be supplied for such a scan, either.) Also, there is no provision for index-only scans with <function>amgetbitmap</function>, since there is no way to return the contents of index tuples. Finally, <function>amgetbitmap</function> does not guarantee any locking of the returned tuples, with implications spelled out in <xref linkend="index-locking"/>. amgettupleを使用する代わりに、amgetbitmapを使用して、一回の呼出しですべてのタプルを取り出してインデックススキャンを行うことができます。 これはアクセスメソッド内でのロック/ロック解除という過程を防ぐことができますので、amgettupleよりもかなり効率的です。 実際には、amgetbitmapamgettuple呼び出しを繰り返すことと同じ効果を持つはずですが、物事を単純化するために複数の制限を加えています。 まず第一に、amgetbitmapは一回ですべてのタプルを返し、スキャン位置の記録と位置戻しをサポートしません。 第二に、特定の順序付けをまったく持たないビットマップの中にタプルが返されます。 これはamgetbitmapdirection引数を取らない理由です。 (順序付け演算子はこのようなスキャンでは決して与えられません。) また、amgetbitmapによるインデックスオンリースキャンは提供されていません。なぜなら、インデックスタプルの内容を返す手段がないからです。 最後に、amgetbitmapは返されたタプルに関し、64.4に記載した意味でのロックを保証しません。

Note that it is permitted for an access method to implement only <function>amgetbitmap</function> and not <function>amgettuple</function>, or vice versa, if its internal implementation is unsuited to one API or the other. アクセスメソッドの内部実装がどちらか片方のAPIにそぐわない場合、amgettupleを実装せずamgetbitmapのみを実装、またはその逆も許されていることに注意してください。