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

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

<title>Index Uniqueness Checks</title>

<productname>PostgreSQL</productname> enforces SQL uniqueness constraints using <firstterm>unique indexes</firstterm>, which are indexes that disallow multiple entries with identical keys. An access method that supports this feature sets <structfield>amcanunique</structfield> true. (At present, only b-tree supports it.) Columns listed in the <literal>INCLUDE</literal> clause are not considered when enforcing uniqueness. PostgreSQLは、SQLの一意性制約を一意性インデックスを使用して強制します。 このインデックスでは、同一キーに対し複数の項目を許しません。 この機能をサポートするアクセスメソッドはamcanuniqueを真に設定します。 (現時点ではb-treeのみがこれをサポートします。) INCLUDE句内の列のリストは、一意性制約の強制時には考慮されません。

Because of MVCC, it is always necessary to allow duplicate entries to exist physically in an index: the entries might refer to successive versions of a single logical row. The behavior we actually want to enforce is that no MVCC snapshot could include two rows with equal index keys. This breaks down into the following cases that must be checked when inserting a new row into a unique index: MVCCのため、インデックス内に物理的に重複した項目が存在できることが常に必要です。 これらの項目は1つの論理的な行の連続的なバージョンを示します。 実際に強制させたい動作は、MVCCスナップショットが同じインデックスキーを持つ行を2つ含めないことです。 一意性インデックスに新しい行を挿入する時に検査しなければならない状況を以下のように分割することができます。

Furthermore, immediately before reporting a uniqueness violation according to the above rules, the access method must recheck the liveness of the row being inserted. If it is committed dead then no violation should be reported. (This case cannot occur during the ordinary scenario of inserting a row that's just been created by the current transaction. It can happen during <command>CREATE UNIQUE INDEX CONCURRENTLY</command>, however.) さらに、上記規則に従った一意性違反を報告する直前に、アクセスメソッドは挿入される行の有効性を再度検査しなければなりません。 もし、無効なコミットであれば、違反を報告してはいけません。 (現在のトランザクションによって作成された通常の行の挿入という状況では、これは発生することはありません。 しかし、これはCREATE UNIQUE INDEX CONCURRENTLY中に発生することがあります。)

We require the index access method to apply these tests itself, which means that it must reach into the heap to check the commit status of any row that is shown to have a duplicate key according to the index contents. This is without a doubt ugly and non-modular, but it saves redundant work: if we did a separate probe then the index lookup for a conflicting row would be essentially repeated while finding the place to insert the new row's index entry. What's more, there is no obvious way to avoid race conditions unless the conflict check is an integral part of insertion of the new index entry. インデックスアクセスメソッドにこうした試験を自身で行うことを要求します。 これは、インデックスの内容に対して重複するキーを持つことを示している任意の行のコミット状態を検査するために、ヒープまでアクセスしなければならないことを意味します。 これが醜くモジュール化されないことには疑う余地はありません。 しかし、余計な作業を防ぐことができます。 もし分離された探査を行ったとすると、新しいインデックス項目を挿入する場所を検索する時、競合する行に対するインデックス検索がどうしても繰り返されます。 さらに、競合検査がインデックス行の挿入部分で統合されて行われない限り、競合状態を防ぐ明確な方法がありません。

If the unique constraint is deferrable, there is additional complexity: we need to be able to insert an index entry for a new row, but defer any uniqueness-violation error until end of statement or even later. To avoid unnecessary repeat searches of the index, the index access method should do a preliminary uniqueness check during the initial insertion. If this shows that there is definitely no conflicting live tuple, we are done. Otherwise, we schedule a recheck to occur when it is time to enforce the constraint. If, at the time of the recheck, both the inserted tuple and some other tuple with the same key are live, then the error must be reported. (Note that for this purpose, <quote>live</quote> actually means <quote>any tuple in the index entry's HOT chain is live</quote>.) To implement this, the <function>aminsert</function> function is passed a <literal>checkUnique</literal> parameter having one of the following values: 一意性制約が遅延可能である場合はさらに複雑になります。 新しい行向けのインデックス項目を挿入可能にする必要があります。 しかし一意性違反エラーは文の終わりまたはそれ以降まで遅延されます。 不要なインデックス検索の繰り返しを防ぐために、インデックスアクセスメソッドは初期の挿入の間に前座の一意性検査を行わなければなりません。 これが現存するタプルとまったく競合がないことを示した場合、それで終了です。 さもなければ、制約を強制する時に再検査を行うようスケジュールします。 再検査の時点で対象のタプルと同じキーを持つ何らかの他のタプルが存在すると、エラーを報告しなければなりません。 (この目的のために存在するは実際にはインデックス項目のHOTチェイン内に何らかのタプルが存在することを意味します。) これを実装するために、aminsertは以下のいずれかの値を持つcheckUniqueパラメータを渡されます。