更新


update文では、インデックスの順序を維持するために、 変更されたインデックスを移動させなければなりません。そのために、 データベースは古いエントリを削除し、新しいエントリを新しい場所に作ります。 応答時間は通常、対応するdelete文とinsert文を 同時に実行したのとほぼ同じになります。

updateのパフォーマンスは、 insertdeleteと同じく テーブルに作られたインデックスの数に依存します。唯一の違いは、 update文は必要な列しか選択しない場合が多いので、 全列を更新しなくても良い事です。従って、update文では テーブルの全てのインデックスではなく、更新される列が含まれる インデックスだけを更新すれば良いのです。

図 8.3は、 2つのupdate文の応答時間を表したものです。 1つは全列を更新するため全インデックスに影響がある場合、 もう1つは1列しか変更しないのでインデックス1つにしか影響がない場合です。

図8.3 インデックスと列数による更新のパフォーマンス変化


全列を更新するupdate文では、前の節で見たのと同じように、 インデックスが増えるごとに応答時間が増えています。 1つのインデックスにしか影響がないupdate文の 応答時間は、他のインデックスに影響を与えないため、インデックス数が 増えてもほとんど変わりません。

updateのパフォーマンスを最適化するには、 変更する列のみを更新するよう注意を払う必要があります。手動で update文を実行するなら、そんなことは当たり前に 思えるかもしれません。しかし、ORMツールは毎回全ての列を更新する update文を生成してしまう事があります。例えばHibernateは、ダイナミックアップデート モードが無効な時は、常に全列を更新してしまいます。 バージョン4.0からは、デフォルトでこの機能は有効になりました。

ORMツールを使う場合、生成されたSQLを確認するために、 開発環境では時々クエリのロギング機能を有効にしてみるのが良いでしょう。 「SQLのロギングを有効にする」では 広く使われているORMツールでSQLのロギングを有効にする方法を 簡単に説明しています。

考えてみよう

insertdeleteが、 テーブルに作られた全てのインデックスに影響を与えない場面は あり得るでしょうか?

Photo of Markus Winand
Markus Winand氏は、開発者がSQLパフォーマンスを改善するお手伝いをしています。 彼は、SQL Performance Explainedの 著者でもあり、出張トレーニングhttp://winand.at/での リモート講義も 行っています。