web-dev-qa-db-ja.com

すべてのパーティションのインデックスを削除するにはどうすればよいですか?

パーティション分割されたテーブルにインデックスを作成すると、各パーティションは独自のインデックスを取得します。メインインデックスを削除しても、これらは削除されません。

これを行う簡単な方法はありますか?

最上位のインデックス名とパーティションサフィックスが一致するすべてのインデックスを検索する関数を作成しました。この関数は、パーティションで作成されたインデックスに対して正常に機能します。

ただし、Greenplumがデフォルトのパーティション分割によって新しいパーティションを追加すると、まったく異なる命名規則でそのパーティションの新しいインデックスが生成されます。

既存のパーティションには、indexname_1_prt_partitionnameのような名前が付けられます

新しいパーティションにはtablename_1_prt_partitionname_indexcolumnのような名前が付けられます

名前が一致しない場合、新しいパーティションインデックスが親インデックスの一部であることをどのようにして特定できるでしょうか?または、一致する2つの異なるパターンでインデックス削除を2回呼び出すだけですか?

以下のBellのクエリ、またはパーティションインデックスを取得するように調整されたクエリ(ヘッドインデックスを既に削除している場合)を使用します。

SELECT child_index.indexrelid::regclass
  FROM pg_index AS partition_index
    -- Find the partition that the partition index is on
    INNER JOIN pg_partition_rule parindex_rule ON parindex_rule.parchildrelid = partition_index.indrelid
    -- Follup up to the partitioning scheme
    INNER JOIN pg_partition ON pg_partition.oid = parindex_rule.paroid
    -- Follow the links through to the individual partitions
    INNER JOIN pg_partition_rule ON pg_partition_rule.paroid = pg_partition.oid
    -- Find the indexes on each partition
    INNER JOIN pg_index AS child_index ON child_index.indrelid = pg_partition_rule.parchildrelid
      -- Which are on the same field as the named index
      AND child_index.indkey = partition_index.indkey
      -- Using the same comparison operator
      AND child_index.indclass = partition_index.indclass
  -- Filtered for the index we're trying to drop
  WHERE partition_index.indexrelid = 'schema.partitionindexname'::regclass
6
PhilHibbs

Greenplumは(バージョン4.3.8のように)パーティションのインデックスをベーステーブルのインデックスにリンクするカタログのレコードを維持しません。最良のオプションは、パーティションを追跡し、基本インデックスの定義と一致するパーティション上のインデックスを見つけることです。

CREATE OR REPLACE FUNCTION drop_child_indexes (index_name varchar)
RETURNS VOID
AS
$functionBody$
DECLARE
  child_index_name varchar;
BEGIN

  FOR child_index_name IN
    SELECT child_index.indexrelid::regclass
      FROM pg_index AS parent_index
        -- Find the partitioning scheme for the table the index is on
        INNER JOIN pg_partition ON pg_partition.parrelid = parent_index.indrelid
        -- Follow the links through to the individual partitions
        INNER JOIN pg_partition_rule ON pg_partition_rule.paroid = pg_partition.oid
        -- Find the indexes on each partition
        INNER JOIN pg_index AS child_index ON child_index.indrelid = pg_partition_rule.parchildrelid
          -- Which are on the same field as the named index
          AND child_index.indkey = parent_index.indkey
          -- Using the same comparison operator
          AND child_index.indclass = parent_index.indclass
      -- Filtered for the index we're trying to drop
      WHERE parent_index.indexrelid = $1::regclass::oid
      -- Drop leaves first, even if it doesn't really matter in this case
      ORDER BY pg_partition.parlevel DESC

LOOP
  RAISE NOTICE '%', child_index_name||' ';
  EXECUTE 'DROP INDEX '||child_index_name||';';
END LOOP;

END
$functionBody$
LANGUAGE plpgsql;

同じ定義(フィールド、比較演算子)を持つ別のインデックスがある場合、そのパーティションインデックスも削除されます。完全な答えではありませんが、部分文字列のマッチングよりは優れています。

6
Bell

これに対する私の新しい解決策は、新しいパーティションを作成するときにインデックスの名前を変更することです。パーティションの作成はplsqlプロシージャですでに行っているため、プロセスは次のようになります。

  1. 新しいパーティションを作成する
  2. 新しいパーティションにインデックスがあるかどうかを確認します
  3. 各インデックスの列リストと一致する親テーブルインデックスの名前を確認します
  4. インデックスの名前を変更して、対応する親テーブルのインデックスと一致させます

このようにして、インデックスは常に一貫した名前を持ち、重複することはありません。つまり、列リストのマッチングではなく、名前のマッチングを使用して子インデックスを削除できます。動作するようになったらコードを投稿します。

0
PhilHibbs