大きくなり始めているOracle11gのインストールがあります。このデータベースは、クラスター上で実行されている並列最適化システムのバックエンドです。プロセスへの入力は、最適化ステップからの出力とともにデータベースに含まれています。入力には、ロート構成データといくつかのバイナリファイル(11gのSecureFilesを使用)が含まれます。出力には、現在DBに保存されている1D、2D、3D、および4Dデータが含まれます。
DB構造:
/* Metadata tables */
Case(CaseId, DeleteFlag, ...) On Delete Cascade CaseId
OptimizationRun(OptId, CaseId, ...) On Delete Cascade OptId
OptimizationStep(StepId, OptId, ...) On Delete Cascade StepId
/* Data tables */
Files(FileId, CaseId, Blob) /* deletes are near instantateous here */
/* Data per run */
OnedDataX(OptId, ...)
TwoDDataY1(OptId, ...) /* packed representation of a 1D slice */
/* Data not only per run, but per step */
TwoDDataY2(StepId, ...) /* packed representation of a 1D slice */
ThreeDDataZ(StepId, ...) /* packed representation of a 2D slice */
FourDDataZ(StepId, ...) /* packed representation of a 3D slice */
/* ... About 10 or so of these tables exist */
刈り取りスクリプトが毎日登場し、DeleteFlag = 1
のケースを探し、DELETE FROM Case WHERE DeleteFlag = 1
を続行して、カスケードを続行できるようにします。
この戦略は読み取り/書き込みには最適ですが、データをパージしたいときに機能を上回っています。摩擦によってケースが削除されると、サイズにもよりますが20〜40分かかり、アーカイバのスペースが過負荷になることがよくあります。製品の次のメジャーバージョンは、問題を解決するために「ゼロから」アプローチを取ります。次のマイナーリリースは、データベースに保存されているデータの範囲内にとどまる必要があります。
したがって、マイナーリリースでは、削除のパフォーマンスを向上させることができ、せいぜいデータベースに中程度の変更を加える必要があるアプローチが必要です。
Case
でINTERVALを実行し、残りでREFを実行したいと思います ただし、サポートされていません 。トリガーを介してOptimizationRun
をCaseId
で手動で分割する方法はありますか?問題を説明するために、ケースごとの問題のデータは15MiBから1.5GiBの範囲で、20kから2M行の範囲です。
更新:DBの現在のサイズは約1.5TBです。
データベースにとって、データの削除は大変な仕事です。イメージの前に作成し、インデックスを更新し、REDOログを書き込み、データを削除する必要があります。これは遅いプロセスです。このタスクを実行するためのウィンドウを用意できる場合、最も簡単で最速の方法は、必要なデータを含む新しいテーブルを作成することです。古いテーブルを削除し、新しいテーブルの名前を変更します。これにはいくつかのセットアップ作業が必要です。これは明らかですが、作成することは非常に可能です。それほど劇的ではないステップは、削除が行われる前にインデックスを削除することです。私の投票はCTAS(Create Table As Select from)に行き、新しいテーブルを作成します。優れたパーティショニングスキーマは確かに役立ちます。おそらく次のリリースでは、Oracleはインターバルパーティショニングと参照パーティショニングを組み合わせることができます。持っていてとてもいいです。
ロギングの無効化....削除に対しては実行できませんが、CTASはnologgingを使用できます。準備ができたらバックアップを作成し、データファイルがある場合は必ずスタンバイデータベースに転送してください。
いくつかの考え:
すべての外部キーにインデックスがあると思います。 ON DELETE CASCADEは、Caseの削除が完了するまで行レベルのロックを保持し、インデックスがない場合はテーブルのロックを保持します。もちろん、非常に低速です。
延期された制約はありますか?これにより、Oracleがさまざまなテーブルの削除をカスケードする際の速度が低下する可能性があります。
(削除カスケードに依存するのではなく)影響を受けるすべてのテーブルに対して個別に削除を実行しようとしましたか?それほど簡単ではありませんが、驚くかもしれません。
編集:
もう1つ考えました。ケーステーブルでソフト削除を行うことを検討できます。つまり、そのケースを検討する必要があるかどうかをアプリに通知するステータスフィールドがあります。このフラグにはさまざまな値がありますが、アクティブの場合は「A」、非アクティブの場合は「I」である可能性があります。他のテーブルへの結合で常にCaseを駆動/プライマリテーブルとして使用していると仮定すると、HARDによる削除をすべて一緒に回避できます(必要に応じて、スケジュールに関係なく時間のクリーンアップを行うこともあります)。もちろん、アプリはこのフラグを認識する必要があり、Caseテーブルに再び参加する必要があります。あなたの状況に合うかもしれないし、合わないかもしれません...
CASCADE DELETE
は、内部的にslow-by-slow、er、row-by-rowで実行されます。
いくつかのオプション:
パージジョブのスナップショットを作成して、CTASを使用してスクラッチテーブルにパージするすべてのケースを作成します。次に、パージジョブをそのテーブルでループさせ、各ケース(およびその子)を個別に削除します。これは、特に何百万もの子孫行に遭遇した場合、不快になる可能性があります。最近[businessredacted]でプロセスの1つを変更して、問題のある子カウントを持つ最終的な親を特定し、問題のある子テーブルに対する削除にrownum
リミッターを使用する必要がありました( s)。高速ではありませんが、少なくとも、トランザクションの大きさに上限を設けることで、元に戻す/やり直しの管理の観点から安全です。
便宜上CASCADE DELETE
を使用している場合、常にそうできるとは限りません。依存関係ツリーから「ボトムアップ」で削除する、より高度なパージルーチンを作成する必要があります。
ソフト削除で元に戻す/やり直しを生成する余裕がある場合は、DeleteFlag
で最終的な親を範囲パーティション化し、次にENABLE ROWMOVEMENTを使用してすべてのテーブルの子BY REFERENCE
をパーティション分割できます。ソフト削除されたときに行を移動するための元に戻す/やり直しのコストが発生しますが、最終的にパージするときが来ると、DeleteFlag = 1
のパーティションが切り捨てられます。
ストレージの追加は比較的安価です。日付ベースの保持オプションがある場合はそれを使用し、ソフト削除オプションでアプリケーションのフロントエンドからデータを非表示にします。エレガントではありませんが、CASCADE DELETE
もエレガントです。
ライブデータベースにはお勧めしません。
Enterprise Managerを使用してAWRレポートを作成し、それを実行します statspackanalyzer これにより、システムのボトルネックに関する詳細な手順がわかります。 AWRレポートは、データベースが特定の時間に実行したことと、それにかかった時間に関するすべての種類のデータを含むテキストファイルです。そのstatspackアナライザーは、何をすべきかを指示する一種の自動DBAではありません。
Statspack Analyzerが有用である可能性があることを通知し、I/Oの分散に使用できるアイドルディスクがいくつかあるまで、パーティションを忘れます。
切り捨てについては考えないでください。コミットを強制します...
ところで、私はStatspack Analyzerとは提携していませんが、特にDBAがない場合は、Oracleにとって非常に実行可能な一般的なチューニングアプローチだと思います。