インデックスが存在しない場合は作成します


60

インデックスが存在しない場合にインデックスを追加できる機能に取り組んでいます。比較するインデックスのリストを取得できないという問題に直面しています。何かご意見は?

これは、次のコードで解決される列作成の問題と同様の問題です:https :
//stackoverflow.com/a/12603892/368511


試すことができます:SELECT * from pg_indexes where schemaname = '[schemaname]' and indexname = '[indexname]'。[スキーマ名]と[インデックス名]を適切な値に置き換えます。参照:postgresql.org/docs/9.1/static/view-pg-indexes.html
jbarrameda

回答:


102

PostgreSQLのインデックス名

  • インデックス名は、単一のデータベーススキーマ全体で一意です。
  • インデックス名は、同じスキーマ内の他のインデックス、(外部)テーブル、(実体化)ビュー、シーケンス、またはユーザー定義の複合型と同じにすることはできません。
  • 同じスキーマ内の2つのテーブルに同じ名前のインデックスを付けることはできません。(論理的にフォローします。)

インデックスの名前を気にしない場合は、Postgresに自動的に名前を付けてください:

CREATE INDEX ON tbl1 (col1);

(ほぼ)同じです:

CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);

Postgresが名前の衝突を避けて、次の自由な名前を自動的に選択することを除いて:

tbl1_col1_idx 
tbl1_col1_idx2
tbl1_col1_idx3
...

やってみなよ。しかし、明らかに、複数の冗長なインデックスを作成したくないでしょう。そのため、盲目的に新しいものを作成するのは得策ではありません。

存在のテスト

Postgres 9.3以前

テストする非常に簡単な方法は、スキーマ修飾名をregclass以下にキャストすることです。

SELECT 'myschema.myname'::regclass;

例外がスローされた場合、名前は無料です。
または、例外をスローせずに同じことをテストするには、DOステートメントで使用します:

DO
$$
BEGIN
   IF NOT EXISTS (
      SELECT
      FROM   pg_class c
      JOIN   pg_namespace n ON n.oid = c.relnamespace
      WHERE  c.relname = 'mytable_mycolumn_idx'
      AND    n.nspname = 'myschema'
   ) THEN

        CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
    END IF;
END
$$;

このCREATE INDEX CONCURRENTLYバリアントは外部トランザクションでラップできないため、これは機能しません。以下の@Gregoryによるコメントを参照してください。

このDOステートメントはPostgres 9.0で導入されました。以前のバージョンでは、同じことを行う関数を作成する必要があります。マニュアルの
詳細。マニュアルのインデックス に関する基本。pg_class

Postgres 9.4

新しい関数to_regclass()を使用して、例外をスローせずにチェックできます。

DO
$$
BEGIN
   IF to_regclass('myschema.mytable_mycolumn_idx') IS NULL THEN
      CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
   END IF;

END
$$;

その名前のインデックス(または別のオブジェクト)が存在しない場合はNULLを返します。見る:

Postgres 9.5

現在利用可能:

CREATE INDEX IF NOT EXISTS ...

それはにも有効ですCREATE INDEX CONCURRENTLY IF NOT EXISTS

ただし、マニュアルでは次のように警告しています:

既存のインデックスが作成されたもののようなものであるという保証はないことに注意してください。

オブジェクト名の単純なチェックです。ここのすべてのバリアントに適用されます。


7
すばらしい答えですが、CONCURRENTLYこの方法ではインデックスを追加できないことに注意してください。取得しERROR: CREATE INDEX CONCURRENTLY cannot be executed from a function or multi-command stringます。
グレオルツォフ14

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.