DELETE、INSERT と UPDATE のパフォーマンスの違い
DELETE と INSERT の組み合わせはデータ登録と更新を「まったく同じロジック」で動作させることができる。
そのためコーディング量を少なくすることができ、退屈で大量にある同じようなデータメンテナンス画面など使用したい誘惑に駆られる手法の1つである。
その DELETE、INSERT と UPDATE で同じような処理を書いた場合、どちらかにデータベース的に影響があるかについて気にしたことはあるだろうか?
結論から先に言うと、UPDATE の方が DELETE 〜 にくらべ処理が少なく、格納効率の悪化が発生しにくいと言える。
UPDATE の優位性については2つのケースについて考えることができる。
但し、一方に書いてあることが他方に全く関係ないということではなく影響度が低いと考えている。
散発的に単発更新が発生する場合
通常、この場合には、その処理ごとにトランザクションを確定する (COMMIT を発行する)。
1レコードのみ DELETE、INSERT ⇒ COMMIT または、 1レコードの UPDATE ⇒ COMMIT という非常に小さなトランザクションであると思う。
DELETE、INSERT の場合、通常表では DELETE で削除した同じブロックの同じ位置に INSERT のデータが格納されることは皆無である。実際どこに格納されるか色々な要素が関連する(※ 関連事項参照)。
このデータの再配置によって、データブロックに
おける平均格納行数が低下し、単発で発生することで関連性の高い仲間のデータの塊(データブロック)の中からつまみ出される形になる。すなわち、クラスタ化係数が悪化するということである。
これらは、以後のすべての DML の速度に影響を及ぼす。インデックス・スキャンにもテーブル・フルスキャンにも影響がある重要なパラメータである。
しかし、削除によるデータの再配置によって行移行が発生しているレコードに対して断片化を解消できるという側面もある。
大量のデータを一気に操作する場合
大量のデータを削除してデータをインサートする場合には、DELETE、INSERT による ROWID の変更がポイントになる。
インデックスには、キーになるデータと格納位置を示す ROWID が格納されている。
テーブルにインデックスが設置されている場合、そのすべてのインデックスの該当するレコードの ROWID を変更しなければならない。この作業は設置してあるインデックスの個数分で発生するため大量のデータを一気に処理する場合に、その更新作業が相当量になることは容易に想像できる。
データ更新時の豆知識:インデックスの削除とインサート処理において、表データが削除されても同じキーのデータを挿入すれば、インデックスの同じリーフ・ブロックの同じ位置が使用される可能性は高い(※)。
(※) インデックスのリーフ内のデータは、テーブルのデータが削除されることで空き領域になるが再構成までは行わない。
これは個々のトランザクションのパフォーマンスを向上させるためという理由と、後続のトランザクションで同じデータが再度挿入されることを想定しているための処置である。
このような処置がすべてのケースでよい結果を生むとは限らないので、定期的に監視してメンテナンスが必要な場合にはインデックスの再構築を行なう。(半期や年単位で確認する程度だと思う)
データブロック・ストレージ関連事項
- 空き領域と再利用までのしきい値
- 表領域の管理の種類
- 空き領域と使用済みの管理の種類