7

成熟した Oracle データベース アプリケーション (10 年以上実稼働) があり、その間、不要になった古いデータを削除するために独自に考案したスクリプトを使用してきました。これらは、適切なテーブルに対して削除ステートメントを発行することによって機能し、頻繁なコミットを伴うループで、I/O によるシステムの過負荷や過度の undo スペースの使用を回避します。

ほとんどの場合、それらは正常に機能します。これらは毎日実行され、システムから最も古い日付のデータを削除するのに約 1 時間かかります。私が持っている主な懸念は、このすべての削除がテーブルとインデックスに与える影響と、システムに過度の負荷をかけていなくても、1 日分のデータをその短い時間で削除すると吹き飛ばされるという事実です。インスタンスのバッファ キャッシュを削除すると、キャッシュが徐々に復元されるため、次の数時間は後続のクエリの実行がわずかに遅くなります。

何年もの間、私たちはより良い方法を検討してきました。以前、人々が古いデータのリーピングを管理するためにパーティション分割されたテーブルを使用していたと聞いたことがあります。このアプローチの主な欠点は、リープ ルールが「X 月を削除する」を超えていることです。ユーザーは、キー値に基づいてデータがシステムに保持される期間を指定できます (たとえば、請求書テーブルでは、アカウント foo は 3 か月後に削除できますが、アカウント bar は 2 年間保持する必要がある場合があります)。

参照整合性の問題もあります。Oracle のドキュメントでは、主にテーブルがハイパーキューブである傾向があるデータ ウェアハウスのコンテキストでデータをパージするためのパーティションの使用について説明しています。私たちのものは OLTP の終点に近く、月 X のデータが月 Y のデータと関係を持つことはよくあることです。

キャッシュ ブローアウトについては、専用のバッファ キャッシュの設定について少し読んだことがありますが、ユーザーごとまたはトランザクションごとではなく、テーブルごとのようです。キャッシュを保持するために、一度削除されたデータを保持する必要がないため、リーピング ジョブがいつでも 1 つのトランザクションに相当するデータのみをキャッシュに保持するようにしたいと考えています。

予見可能な将来のために削除を使用して行き詰まっていますか、それともリープに対処するための他のより賢い方法はありますか?

4

4 に答える 4

4

ほとんどの場合、あなたは削除を行っていると思います。

あなたのケースでパーティションを使用することの難しさについてのあなたのコメントは、おそらくそれらが効果的に使用されるのを妨げます (レコードの種類に応じて異なる削除日が使用されます)。分割できますか?削除日の変更により行の移行が発生する可能性があるため、更新を非常に高価にするという欠点があるため、更新は実際には削除と挿入として実装されます。

それでも、参照整合性の問題により、DDL パーティション操作を使用して古いデータを削除できない可能性がありますが、パーティション分割は、削除する行を物理的にクラスター化する目的で役立つ可能性があるため、削除するために変更する必要のあるブロックが少なくなります。バッファ キャッシュへの影響を軽減します。

于 2009-06-11T17:30:22.323 に答える
0

インデックスを一時的に非アクティブ化し、削除を実行してから再構築するとどうなりますか? 削除のパフォーマンスは向上しますか? もちろん、この場合、スクリプトが正しいことを確認し、適切な削除順序と参照整合性を確保する必要があります。

于 2009-06-12T12:19:04.950 に答える
0

同じ戦略を使用して、同じ問題を抱えています。状況が非常に悪化した場合 (インデックス、テーブルの割り当てが非常に断片化されているなど)、スペース再利用アクションを適用しようとします。

テーブルは行の移動を許可する必要があります (フラッシュバックの場合と同様)。alter table TTT は行の移動を有効にします。テーブル TTT 縮小スペースを変更します。次に、すべてのインデックスを再構築します。

メンテナンスウィンドウをどのように使用しているかわかりません。アプリケーションを常に使用できる必要がある場合は難しくなります。そうでない場合は、オフラインのときに「再パック」を行うことができます。「alter table TTT move tablespace SSSS」は、テーブルが書き換えられるときに混乱を一掃する多くの作業を行います。エクステント管理、サイズなどの新しいストレージ パラメータを指定することもできます。ドキュメントを参照してください。

次のようなスクリプトを使用して、データベース全体のスクリプトを作成します。

SET SQLPROMPT "-- "
SET ECHO OFF
SET NEWPAGE 0
SET SPACE 0
SET PAGESIZE 0
SET FEEDBACK OFF
SET HEADING OFF
SET TRIMSPOOL ON
SET TERMOUT OFF
SET VERIFY OFF
SET TAB OFF
spool doit.sql
select 'prompt Enabling row movement in '||table_name||'...'||CHR (10)||'alter table '||table_name||' enable row movement;' from user_tables where table_name not like '%$%' and table_name not like '%QTAB' and table_name not like 'SYS_%';
select 'prompt Setting initial ext for '||table_name||'...'||CHR (10)||'alter table '||table_name||' move storage (initial 1m);' from user_tables where table_name not like '%$%' and table_name not like '%QTAB' and table_name not like 'SYS_%';
select 'prompt Shrinking space for '||table_name||'...'||CHR (10)||'alter table '||table_name||' shrink space;' from user_tables where table_name not like '%$%' and table_name not like '%QTAB' and table_name not like 'SYS_%';
select 'prompt Rebuilding index '||index_name||'...'||CHR (10)||'alter index '||index_name||' rebuild;' from user_indexes where status = 'UNUSABLE';
spool off
prompt now check and then run @doit.sql
exit
于 2009-06-15T20:58:23.150 に答える
0

インデックスを再構築すれば、削除はそれほど悪くありません。オラクルは、データを含まなくなったページを回復します。

ただし、8i の時点では (おそらく今でも)、有効な参照が含まれなくなったインデックス ページは適切に回復されませんでした。さらに悪いことに、インデックス リーフがチェーンされているため、行を見つけるためにリーフ ノードをたどり始める状況に陥る可能性があります。これにより、パフォーマンスが大幅に低下します。通常は数秒かかるクエリが数分かかる場合があります。低下も非常に突然でした。

増加するキーと定期的に削除されるデータを使用するアプリケーションで、この動作を発見しました (Oracle のバグがあったため、他の人も同様です)。私たちの解決策はキーの一部を逆にすることでしたが、それは日付には役に立ちません。

于 2009-06-11T17:39:39.137 に答える