web-dev-qa-db-ja.com

関数ベースのインデックスでテーブルのスペースを縮小する方法は?

不要な空き領域を削除したいパーティション分割テーブルがあります。通常、次のようなコマンドを実行します。

ALTER TABLE {table name} MODIFY SUBPARTITION {subpartion name} SHRINK SPACE;    
ALTER TABLE {table name} MODIFY PARTITION {partion name} SHRINK SPACE;  

ただし、テーブルには関数ベースのインデックスがあるため、特定のテーブルでエラーが発生します( shrink_clauseの制限 を参照)。

ORA-10631:このオブジェクトにはSHRINK句を指定しないでください

テーブルのインデックスはすべてローカルです。グローバルインデックスはありません。誰かが空きスペースを縮小する解決策を知っていますか?

関数ベースのインデックスの削除、スペースの縮小、インデックスの再作成はオプションではありません。テーブルが非常に大きい(2,000億行、それぞれ20 Tバイト)ので、時間がかかりすぎます。表全体ではなく、いくつかのサブパーティションのみを縮小する必要があります。

また、そのパーティションで関数ベースのインデックスを無効にしようとしましたが( パーティションテーブルの部分インデックス を使用して)、それも機能しませんでした。

3

1つのアイデアは、パーティション交換を使用することです。これにより、一度に1つのパーティションに必要なスペースを縮小できます。私はこれを自分でテストすることができないので、まず開発環境で慎重にテストしてください。これを行うには、少なくとも2つの異なる方法があります。

方法1:

  1. 古いテーブルとまったく同じ列とインデックスを持つ新しいテーブルを作成します。新しいテーブルには1つのパーティションが必要です。
  2. パーティションからすべてのデータをコピーして、新しいテーブルに圧縮します。並列DMLを使用してこれを高速化できます。すべてのデータを再度書き込むので、新しいコピーで無駄になるスペースははるかに少なくなるはずです。
  3. 大きなテーブルでまだ圧縮を使用していない場合は、パーティションを交換する前に新しいテーブルに圧縮を適用できます。
  4. ALTER TABLE ... EXCHANGE PARTITION ... WITH TABLE ...を使用して、パーティションを交換します。
  5. 新しいテーブルを切り捨てます。
  6. 必要に応じて繰り返します。

方法2:

  1. 古いテーブルとまったく同じ列とインデックスを持つ新しいテーブルを作成します。新しいテーブルには1つのパーティションが必要です。
  2. ALTER TABLE ... EXCHANGE PARTITION ... WITH TABLE ...を使用して、1つのパーティションを新しいテーブルに移動します。これは、 Partition Exchange および Database VLDB and Partitioning Guide による関数ベースのインデックスを持つパーティションでも機能するはずです。インデックスはローカルであるため、大きなテーブルのインデックスを無効にするべきではありません。 INCLUDING INDEXESオプションを指定する場合、インデックスは新しいテーブルでもすべて有効である必要があります。
  3. 新しいテーブルに必要なスペースを減らします。 OracleのMOVE機能を使用したいだけかもしれません。関数ベースのインデックスの削除、SHRINK SPACEコマンドの発行、インデックスの再作成を試すことができますが、インデックスを再作成すると、新しいテーブルに多くの不要な空き領域が生じる可能性があります。
  4. 大きなテーブルで圧縮をまだ使用していない場合は、パーティションを戻す前に、それを新しいテーブルに適用できます。
  5. 古いテーブルとのパーティション交換。
  6. 必要に応じて繰り返します。

個人的には方法1の方が好きです。大きなテーブルでの可用性が向上し、少ない作業でより予測可能な結果が得られるはずです。

注意すべき点の1つは、関数ベースのインデックスを持つパーティションを交換するときに、ある時点で統計に何らかの問題があったことです。あなたはそれについてより多くの情報を見つけることができます ここ

1
Joe Obbish