質問

各行にランダムに生成された主キー、メッセージ、およびユーザーが含まれるDBテーブルがあります。各ユーザーには約10〜100のメッセージがありますが、1万〜5万のユーザーがいます。

一度に各ユーザーのメッセージを毎日書きます。テーブルをできる限り小さくするために、新しいメッセージを書き込む前に各ユーザーの古いメッセージを破棄したい。

今、私は効果的にこれを行います:

delete from table where user='mk'

次に、そのユーザーのすべてのメッセージを書き込みます。これを同時に行うスレッドがたくさんあるため、多くの競合が発生しています。

各ユーザーの最新のメッセージセットを保持するための追加要件があります。

DBに直接アクセスできません。いくつかの間接的なフィードバックに基づいて問題を推測しようとしています。私がこのシナリオに注目している理由は、削除クエリが多くの待機時間を示しているためです(これも私の知る限り)と、新たに追加された機能です。

誰でもアドバイスを提供できますか?

次の方が良いですか:

select key from table where user='mk'

そこから個々の行を削除しますか?私はそれがより残忍なロックにつながるかもしれないと考えています。

役に立ちましたか?

解決

いいえ、一連の「行ごと」ではなく、行のセットに対して単一のSQLステートメントを実行することを常にお勧めします。 (またはトムカイトが「スローバイスロー」と呼ぶもの)操作。 「多くの競合を見ている」と言うとき、あなたは正確に何を見ていますか?明らかな質問:列USERはインデックス付けされていますか?

(もちろん、列名は予約語であるため、Oracleデータベースでは実際にUSERにすることはできません!)

編集:列USERはインデックス付けされていないと述べました。これは、削除ごとに最大50K * 100 = 500万行(または最大で10K * 10 = 100,000行)の完全なテーブルスキャンを実行して、わずか10-100行を削除することを意味します。 USERにインデックスを追加すると、問題が解決する場合があります。

他のヒント

すべてのユーザーに対してこれを毎日行う場合、単一のステートメントでテーブルからすべてのレコードを削除するだけではどうですか?または

truncate table whatever reuse storage
/

編集

このアプローチを提案する理由は、プロセスが古いメッセージの消去が先行するユーザーメッセージの毎日のバッチアップロードのように見えるためです。つまり、ビジネスルールは「テーブルには、特定のユーザーに対して1日分のメッセージのみが保持される」ように思われます。このプロセスがすべてのユーザーに対して実行される場合、単一の操作が最も効率的です。

ただし、ユーザーが毎日新しいメッセージセットを取得しない場合 、ユーザーごとに最新のメッセージセットを保持する必要がある補助ルールがあり、テーブル全体をザッピングすると間違っている。

ロックの競合が発生しているのは確かですか?同時実行が多すぎるためにディスクの競合が発生している可能性が高いようです(ただし、関連のない更新)。その解決策は、使用しているスレッドの数を減らすことです。ディスクの競合が少ないほど、総スループットが高くなります。

要件をもう少し明確にする必要があると思います...

たとえば。メッセージを書き込みたいすべてのユーザーがわかっている場合は、IDを一時テーブルに挿入し、IDにインデックスを付けてバッチ削除します。次に、起動するスレッドは2つのことを実行しています。ユーザーのIDを一時テーブルに書き込み、メッセージを別の一時テーブルに書き込みます。次に、スレッドの実行が終了すると、メインスレッドは

DELETE * FROMメッセージINNER JOIN TEMP_MEMBERS ON ID = TEMP_ID

メッセージへの挿入SELECT * FROM TEMP_messges

私はOracle構文に精通していませんが、ユーザーメッセージがすべて連続して行われた場合、それは私がアプローチする方法です。

これが役立つことを願って

DBAに連絡

彼はあなたを助けるためにそこにいます。 DBAがこのような何かのために開発者からアクセスを奪うとき、そのタスクのサポートを提供すると想定されています。コードの完了に時間がかかりすぎて、その時間がデータベースに拘束されているように見える場合、DBAは何が起こっているかを正確に確認し、提案を提供したり、場合によっては何も変更せずに問題を解決したりすることができます。 p>

問題のステートメントを一glするだけで、競合の問題を見ているようには見えませんが、基本的な構造については何も知りません。

本当に、DBAに相談してください。彼は、おそらく最新のCPU展開を計画する代わりに、何か楽しいものを見て楽しむでしょう。

これにより速度が向上する可能性があります:

ルックアップテーブルを作成します:

create table rowid_table (row_id ROWID ,user VARCHAR2(100));
create index rowid_table_ix1 on rowid_table (user);

夜間ジョブを実行します:

truncate table rowid_table;
insert /*+ append */ into rowid_table
select ROWID row_id , user
from table;
dbms_stats.gather_table_stats('SCHEMAOWNER','ROWID_TABLE');

レコードを削除するとき:

delete from table
where ROWID IN (select row_id
                from rowid_table
                where user = 'mk');

あなた自身の提案は非常に賢明なようです。小さなバッチでのロックには2つの利点があります:

  • トランザクションは小さくなります
  • ロックは一度に数行のみに制限されます

バッチでのロックは大幅に改善されるはずです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top