1

私の問題を例で説明しようとしています。私は次のような長期にわたる声明を持っています

UPDATE <table_A>
INNER JOIN <table_B> ON [...]
LEFT JOIN <table_C> ON [...]
LEFT JOIN <table_D> ON [...]
LEFT JOIN <table_E> ON [...]
SET <table_A>.<col_A>=X
WHERE <table_A>.<col_A>=Y AND COALESCE(<table_C>.<id>,<table_D>.<id>,<table_E>.<id> IS NULL

このステートメントは大きなテーブルで実行されます (そのうちの 2 つにはテーブルごとに 700 万行以上が含まれます)。更新には 3 ~ 5 分かかります。別のセッションでは、高い並行性で行われます

UPDATE <table_C> SET <col_A>=Z WHERE <id> IN ([...])

また

DELETE FROM <table_C> WHERE <id> IN ([...])

ビッグランが発生するとUPDATE、これらは同時に発生し、1 ~ 2 分後にロック待機タイムアウトまたはデッドロックで終了します。すべての列にインデックスが付けられます (標準インデックス)。私はすでにやろうとしましたUPDATEDELETESJOIN

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
[BIG UPDATE];
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

しかし、それは役に立ちません。データ<table_A>の整合性はそれほど重要ではありません ( <table_C>...に存在しない行が含まれていても問題ありませ<table_E>ん)。最も重要なことは、小さなUPDATE/ DELETEs on <table_C>...<table_E>が処理されていることです。

4

1 に答える 1

0

ライブデータベースでこれほど大きな更新を実行することは一般的に悪い考えなので、大きな更新を分解することをお勧めします。

これが最も最適化された方法ではありませんが、自分で最適化できると確信しています。

ループで実行:

  1. SELECT Id, ColA FROM TableA ORDER BY Id DESC LIMIT 10 OFFSET (iteration)*10
  2. 2番目のループ、前の結果から行を取得しますtableA.colA=Y
    。2.1。SELECT Id FROM TableB WHERE ID=id_from_current_iteration
    2.2。SELECT Id FROM TableC WHERE ID=id_from_current_iteration
    2.3前の両方のクエリがnullを返した場合は、次の手順に進みます。それ以外の場合は、次の反復に進みます。2.4UPDATE TableA SET ColA=X WHERE ID=id_from_current_iteration

言い換えれば、結合を避けてください。
これには1回の更新よりも時間がかかりますが、機能します。
それを最適化するための最初のステップは、クエリのバッチ処理です。

于 2013-02-16T21:48:33.627 に答える