★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 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

51.5. インデックス一意性検査

PostgreSQLは、SQLの一意性制約を一意性インデックスを使用して強制します。 このインデックスでは、同一キーに対し複数の項目を許しません。 この機能をサポートするアクセスメソッドはpg_am.amcanuniqueを真に設定します。 (現時点ではb-treeのみがこれをサポートします。)

MVCCのため、インデックス内に物理的に重複した項目が存在することができることが常に必要です。 この項目は、1つの論理的な行の連続的なバージョンを示します。 実際に強制させたい動作は、MVCCスナップショットが同じインデックスキーを持つ行を2つ含めないことです。 一意性インデックスに新しい行を挿入する時に検査しなければならない状況を以下のように分割することができます。

さらに、上記規則に従った一意性違反を報告する直前に、アクセスメソッドは挿入される行の有効性を再度検査しなければなりません。 もし、無効なコミットであれば、違反を報告してはいけません。 (現在のトランザクションによって作成された通常の行の挿入という状況では、これは発生することはありません。 しかし、これはCREATE UNIQUE INDEX CONCURRENTLY中に発生することがあります。)

インデックスアクセスメソッドにこうした試験を自身で行うことを要求します。 これは、インデックスの内容に対して重複するキーを持つことを示している任意の行のコミット状態を検査するために、ヒープまでアクセスしなければならないことを意味します。 これが醜くモジュール化されないことには疑う余地はありません。 しかし、余計な作業を防ぐことができます。 もし分離された探査を行ったとすると、新しいインデックス項目を挿入する場所を検索する時、競合する行に対するインデックス検索がどうしても繰り返されます。 さらに、競合検査がインデックス行の挿入部分で統合されて行われない限り、競合状態を防ぐ明確な方法がありません。

一意性制約が遅延可能である場合はさらに複雑になります。 新しい行向けのインデックス項目を挿入可能にする必要があります。 しかし一意性違反エラーは文の終わりまたはそれ以降まで遅延されます。 不要なインデックス検索の繰り返しを防ぐために、インデックスアクセスメソッドは初期の挿入の間に前座の一意性検査を行わなければなりません。 これが現存するタプルとまったく競合がないことを示した場合、それで終了です。 さもなければ、制約を強制する時に再検査を行うようスケジュールします。 再検査の時点で対象のタプルと同じキーを持つ何らかの他のタプルが存在すると、エラーを報告しなければなりません。 (この目的のために"存在する"は実際には"インデックス項目のHOTチェイン内に何らかのタプルが存在する"ことを意味します。) これを実装するために、aminsertは以下のいずれかの値を持つcheckUniqueパラメータを渡されます。