1

私は5 GBのテーブルを持っていますが、今は以下のように削除しようとしていました:

delete  from tablename
where to_char(screatetime,'yyyy-mm-dd') <'2009-06-01' 

しかし、それは長く実行され、応答がありません。その間、誰かがこれをブロックしているかどうかを以下で確認しようとしました:

select l1.sid, ' IS BLOCKING ', l2.sid
from v$lock l1, v$lock l2
where l1.block =1 and l2.request > 0
and l1.id1=l2.id1
and l1.id2=l2.id2

しかし、ブロッキングも見つかりませんでした。

この大きなデータを問題なく削除するにはどうすればよいですか?

4

4 に答える 4

1

5GB は、テーブル サイズの有用な測定値ではありません。行の総数が重要です。合計に対する割合として削除する行の数が重要です。行の平均の長さが重要です。

screatetime削除する行の割合が小さい場合は、後で削除するインデックスを作成する価値があるかもしれません。これは、操作全体に時間がかかることを意味する場合がありますが、重要なことに、行の削除にかかる時間を短縮できます。

一方、大量の行を削除する場合は、

  1. 'create table t1_copy as select * from t1 where screatedate >= to_date('2009-06-01','yyyy-mm-dd')` を使用してテーブルのコピーを作成します
  2. コマンドを使用してテーブルを交換しrenameます。
  3. 制約、インデックスを新しい T1 に再適用します。

心に留めておくべきもう 1 つのことは、削除はロールバックにより多くの情報を必要とするため、他のトランザクションよりも多くの UNDO を消費するということです。そのため、レコードが長い場合や多数の場合、DBA は UNDO テーブルスペース (まだ使用している場合はロールバック セグメント) を確認する必要がある場合があります。

最後に、時間が実際にどこに向かっているのかを調べる調査を行いましたか? DELETE ステートメントは単なる別のクエリであり、通常のチューニング トリックを使用して取り組むことができます。

于 2010-02-02T10:31:04.433 に答える
1

最初にテーブルをロックすると、はるかに高速に実行されます。Rene の提案に従って、where 句も変更します。

LOCK TABLE tablename IN EXCLUSIVE MODE;

DELETE FROM tablename
where screatetime < to_date('2009-06-01','yyyy-mm-dd');

編集:テーブルが常にアクセスされているため、テーブルをロックできない場合は、サラミ戦術を選択してそれらの行を削除できます。

BEGIN
  LOOP
    DELETE FROM tablename
      WHERE screatetime < to_date('2009-06-01','yyyy-mm-dd')
        AND ROWNUM<=10000;
    EXIT WHEN SQL%ROWCOUNT=0;
    COMMIT;
  END LOOP;
END;

全体として、これは遅くなりますが、ロールバック セグメントがバーストすることはなく、別のセッションで進行状況を確認できます (つまり、tablename の行数が減少します)。また、何らかの理由でそれを強制終了する必要がある場合、ロールバックに永遠にかかることはなく、これまでに行ったすべての作業が失われることはありません。

于 2010-02-02T10:18:45.690 に答える
1
于 2010-02-02T07:49:57.183 に答える
1

screatetime にインデックスがある場合、クエリはそれを使用していない可能性があります。where 句でインデックスを使用できるようにステートメントを変更します。

delete from tablename where screatetime < to_date('2009-06-01','yyyy-mm-dd')
于 2010-02-02T07:52:47.810 に答える