Bulk UPDATEは、関連テーブルの大規模な行を変更する際の重要な手順です。SQLの歴史の中で典型的な実装は、サブクエリまたはJOINを使用したUPDATEです。問題点:実行順序を制御しない大量の更新操作は、多くの行をロックし、ロックのエスカレーションを引き起こし、複数の更新時にデッドロックを引き起こす可能性があります。
解決策:
コード例(PostgreSQL):
UPDATE Orders o SET status = 'archived' FROM Customers c WHERE o.customer_id = c.id AND c.closed = TRUE AND o.status != 'archived';
またはバッチで:
WITH upd AS ( SELECT o.id FROM Orders o JOIN Customers c ON o.customer_id = c.id WHERE c.closed = TRUE AND o.status != 'archived' LIMIT 10000 ) UPDATE Orders SET status = 'archived' WHERE id IN (SELECT id FROM upd);
主な特徴:
同時に類似のテーブルをUPDATEし、範囲を分けないか、逆のフィルターを使用した場合、何が起こるでしょうか?
デッドロックの発生が予想されます:プロセスは同じ行をロックし、互いに待っています。これを避けるために、バッチは重ならないようにするか、厳密に順番に実行する必要があります。
大量のステータス変更について、JOINを介したUPDATEとサブクエリの違いはありますか?
適切なインデックスが存在する場合、主な違いは可読性と特定のDBMSのパフォーマンスにのみ関連します。JOINは通常、最適化ツールがより良いプランを作成するため、より高速です。
UPDATEの代わりにTRUNCATE/DELETEを使用するのはどのような場合ですか?
ビジネスロジックが許可する場合、たとえばアーカイブされたレコードを物理的に削除するか、テーブルをリセットする必要がある場合ですが、単にステータスフラグを変更するだけではありません。しかし、ステータスの大量更新にはUPDATEのみです。
大手オンラインストアで、注文と顧客のステータスを同時に変更するために複数のUPDATEを実行しましたが、インターバルで分割されていませんでした。その結果:相互ロックが発生し、強制的なロールバックが何度も必要になり、未記録のデータがロールバックされました。
利点:
欠点:
大規模なサンプルをバッチに分け、厳密に順番に実行し、フィルターに基づいて必要な行のみが処理されました。
利点:
欠点: