2012-02-13 5 views
1

私は3億の行を持つテーブルを持っています。私はそれから約300万を削除する必要があります。私はこのテーブルにインデックスを持っていません。データは特定の日付列に基づいて削除されます。 Likeオラクルの巨大なテーブルから小さなデータを削除する方法を提案

delete from table where column_name = '1-dec-2010' 

これを実行する最適な解決策は何でしょうか?

  1. 列を索引付けして削除します。
  2. それはすなわち、インデックスが削除した後に、インデックスを更新するインデックス・スキャン+オーバーヘッドを使用します使用してインデックス

を使用せずに削除されるような表を保管してください。索引なしでは、全表スキャンを使用します。だから、100万行のインデックスが全テーブルスキャンよりも優先されたと言われている閾値はありますか?

+0

これは一回限りの仕事ですか、通常の仕事ですか? –

答えて

1

次のオプション(効率のために)持っている:

  1. パーティショニングを。 Enterprise Edition用の追加費用オプション。データが1日に分割されている場合、その日のデータを削除するのは、その日のパーティションを削除するのと同じくらい簡単です。高速、効率的、素晴らしい、しかし高価な(顧客が良い割引を得ることができない限り)。

  2. 新しいテーブルを作成し、保持したいデータを新しいテーブルにコピーします(直接パス挿入を使用)。古いテーブルを落とす。新しい表の名前を変更する(または動的に管理される同義語を使用する)。この場合、索引は有用である可能性がありますが、選択性が良好でないためOracleが無視する可能性が高くなります(データの約1%のみがアクセスされるため、オプティマイザは索引を処理する価値がないと考えるかもしれません)。 このオプションではTom Kyte's commentsを参照してください。

  3. インデックスを使用します。これにより、削除する必要のあるレコードの検索が確実に加速されますが、削除は辛うじて遅くなります(やり直しとすべて)。

+0

ちょっとバラニー、答えに感謝します。これは既存のテーブルなので、パーティションを分割して構造を変更することはありません。 2番目のオプションでは100Mテーブルで試してみましたが、インデックスを使用した単純な削除よりも時間がかかりました。私は180Mレコードのうち3Mを削除してテストしたところでさえ、インデックス付きの削除は非インデックス化された削除よりも高速でした。データが300M以上になると同じことが起こるかどうかはわかりません。 –

0

まあ、データの固定1%を削除していますか?その場合は、パーティション分割を考慮しないでください。

  1. 日付列にインデックスを作成します。
  2. オプティマイザ統計がその索引および表に対して収集されていることを確認してください。

は、次のようにクエリを実行します。

select di.table_name, di.index_name, di.leaf_blocks, 
     di.clustering_factor, dt.blocks 
    from all_indexes di 
     left join all_tables dt 
     on di.table_owner = dt.owner 
     and di.table_name = dt.table_name 
where di.index_name = 'my_new_index' 
  • LEAF_BLOCKSはあなたに インデックスの「データ・ブロック」のラフなサイズを提供します。
  • CLUSTERING_FACTORは、そのインデックスでテーブル全体を読み取るために必要なテーブルI/Oの数が であることを示します。
  • BLOCKSブロックのサイズは です。 CLUSTERING_FACTORBLOCKSの大きさに非常に近い場合

は、表は多かれ少なかれインデックスがであるために記憶されています。だから、

あなたがテーブルの1%を削除している場合、小さいかを確認:

BLOCKS、または((LEAF_BLOCKS + CLUSTERING_FACTOR)/100)

ブロックはかなり大きい場合 - 計算されたよりも - おそらく10倍も大きいのために索引がおそらく削除を高速化します。

関連する問題