他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

69.1. 概要

PostgreSQLには、クラッシュから完全に回復可能なディスク上の永続的なハッシュインデックスの実装が含まれています。 明確な線形順序付けを持たないものも含め、すべてのデータ型がハッシュインデックスでインデックス可能です。 ハッシュインデックスは、インデックスされる値のハッシュ値のみを保存するので、インデックス対象の列のサイズは制限となりません。

ハッシュインデックスは単一列のインデックスのみをサポートし、唯一性のチェックはできません。

ハッシュインデックスは=演算子のみをサポートしており、範囲演算を指定するWHERE句はハッシュインデックスの恩恵をこうむることができません。

各インデックスタプルは単なる4バイトのハッシュ値で、実際の列の値ではありません。 そのため、UUIDやURLのような大きなデータをインデックスすると、ハッシュインデックスはB-treeよりもずっと小さくなるかも知れません。 また、列値が欠損しているとすべてのハッシュ走査が損失がある(lossy)ものになります。 ハッシュインデックスはビットマップインデックス走査と後方走査の一部となるかも知れません。

ハッシュインデックスは、大きなテーブルに対して同値走査を使用するSELECTとUPDATEを多用するワークロードに対して最適です。 B-treeインデックスでは、走査はリーフページが見つかるまで木を降下しなければなりません。 何百万行のテーブルではこの降下走査によりデータをアクセスする時間がかかることがあります。 対照的に、ハッシュインデックスはバケットページを直接アクセスすることが可能で、大きなテーブルでのインデックスアクセスの時間を短縮できる可能性があります。 「論理的なI/O」における時間短縮は、共有バッファ/RAMよりもインデックス/データが大きな時にはより顕著になります。

ハッシュインデックスはハッシュ値の均等ではない分布を想定して設計されています。 バケットページへのアクセスはハッシュ値が均一に分布している時にうまく働きます。 挿入によりバケットページが満杯になると、追加の溢れページが特定のパケットページに連結され、そのハッシュ値に適合するインデックスタプル用の領域を局所的に拡張します。 問い合わせ中にハッシュバケットを走査する際は、すべての溢れページを走査する必要があります。 ですからバランスの崩れたハッシュインデックスは、あるデータに対してはアクセスしなければならないブロックの数という意味では、Bツリーよりも悪いかも知れません。

溢れ出が出るケースを考慮すると、ハッシュインデックスは一意か、ほぼ一意に近いデータあるいは、それぞれのハッシュバケットに少数の行があるデータがもっとも適していると言えます。 問題を避けることができる可能性のある方法として、部分インデックス条件を使って極端に一意ではない値を排除する方法がありますが、多くの場合にこれが適しているとは言えないかも知れません。

Bツリーのように、ハッシュインデックスは単純なインデックスタプルの削除を行います。 これは削除しても安全であると分かるインデックスタプル(アイテム識別子のLP_DEADビットがすでにセットされている)を削除する遅延操作です。 挿入の際にページに領域が見つからない場合は、不要インデックスタプルを削除することによって、新しい溢れページを作成するのを回避しようとします。 その時点でそのページにピンがある場合は削除することはできません。 不要インデックスポインタの削除もVACUUM中に発生します。

可能ならば、VACUUMはインデックスタプルをできるだけ少ない溢れページに押し込むことも試みます。 ある溢れページが空になったらその溢れページは再利用できますが、オペレーティングシステムに返却することはありません。 今の所、REINDEXで再構築する以外にハッシュインデックスを縮小するようにする予定はありません。 バケット数を少なくする予定もありません。

ハッシュインデックスはインデックスされた行数が増えるとバケットページ数も拡張します。 ハッシュキーからバケット番号へのマッピングは、インデックスが徐々に拡張できるように選択されます。 新しいバケットがインデックスに追加されることになったら、存在しているバケットの厳密に一つが「分割」される必要があります。 更新されたハッシュキーからバケット番号へのマッピングにしたがって、タプルが新しいバケットに転送されます。

その拡張はフォアグラウンドで行われるので、ユーザが挿入を実行するのにかかる時間を増加させるでしょう。 ですから、ハッシュインデックスは行数が急激に拡張するテーブルには適していないかもしれません。