web-dev-qa-db-ja.com

PostgreSQLでCREATE INDEX CONCURRENTLYが終了したことを検出する

PostgreSQLでインデックスを同時に作成した場合、いつ終了したかを確認するにはどうすればよいですか?

インデックスの肥大化を解決するためにインデックスを再構築しようとしています。新しいインデックスが完了するまでしばらくの間古いインデックスを保持する必要があるため、いつ終了するかを知る必要があります。

これはPostgreSQL 9.2/3ishです

6
Rory

無効なインデックスのリストを取得できます。

SELECT * FROM pg_class, pg_index WHERE pg_index.indisvalid = false AND pg_index.indexrelid = pg_class.oid;

このクエリにインデックスが表示されている場合は、インデックスが機能せず、インデックスを再作成する必要があります。

REINDEXしないでください。インデックスが同時に再作成されることはありません。インデックスの作成中は書き込み用にテーブルがロックされます。最善の解決策は、無効なインデックスを削除し、CONCURRENTLYフラグで再作成することです。

3
Zaytsev Dmitry

@Roryからのコメントと@Zaytsev Dmitryの回答の情報を組み合わせる:

CREATE INDEX CONCURRENTLYは、インデックスの作成が完了するまで戻りません。したがって、クエリが返されたときにインデックスが作成されることがわかります。

ただし、大きなインデックスを作成している場合は、それが「本当に」まだ実行されているかどうか疑問に思うかもしれません。

「無効な」インデックスのクエリを使用できます。

SELECT * FROM pg_class, pg_index WHERE pg_index.indisvalid = false AND pg_index.indexrelid = pg_class.oid;

...インデックスが結果に表示される場合、失敗しましたまたはまだ進行中

後者を確認する別の方法は、ロックテーブルを確認することです。

SELECT a.datname,
         l.relation::regclass,
         l.transactionid,
         l.mode,
         l.GRANTED,
         a.usename,
         a.query,
         a.query_start,
         age(now(), a.query_start) AS "age",
         a.pid
FROM pg_stat_activity a
JOIN pg_locks l ON l.pid = a.pid
WHERE mode = 'ShareUpdateExclusiveLock'
ORDER BY a.query_start;

CONCURRENTLYはテーブルに排他ロックをかけませんが、このクエリの結果に表示される弱いShareUpdateExclusiveLockを保持します。

ロックがない場合は、インデックスの構築が完了したか、作成が失敗して無効なインデックスが残ったことを意味します。

これら2つのクエリの間で、インデックスが3つの可能な状態(完了/進行中/失敗)のどれであるかを判断できます。

2
Anentropic