更新列がインデックスにない更新ステートメントに対するインデックスの影響


16

私はインデックスが遅くなると人々が言うのを常に見ますupdatedeleteそしてinsert。これは、まるで絶対的なものであるかのように、ブランケットステートメントとして使用されます。

データベースを調整してパフォーマンスを向上させている間、私はこの規則に論理的に矛盾していると思われるこのような状況に出くわします。

SQL Serverでは、他のほとんどのDBMSを使用すると考えられますが、インデックスは指定した特定の列に基づいて作成されます。挿入と削除は常に行全体に影響を与えるため、インデックスに影響を与えることはありませんが、更新はもう少しユニークに見えます。特定の列にのみ影響します。

インデックスに含まれていない列があり、それらを更新する場合、そのテーブル内の他の列にインデックスがあるために、それらは遅くなりますか?

たとえば、私のUserテーブルには、1つまたは2つのインデックス、Identity / Auto Incrementカラムであるプライマリキー、および場合によっては外部キーカラム上の別のインデックスがあります。
電話番号や住所など、インデックスのない列を直接更新すると、どちらの状況でもこのテーブルのインデックスが他の列にあるため、この更新は遅くなりますか?更新している列はインデックスにないため、論理的には、インデックスを更新しないでください。どちらかと言えば、WHERE句でインデックスを使用すると、速度が向上すると思います。


so there is no way they will not affect the indexフィルタされたインデックスを除く
usr

カバーされていない非クラスター化インデックスには、レコードへのポインターが含まれていると思います(通常、テーブルのクラスター化インデックスリーフノードにあります)。(含まれていない属性の)UPDATE中にスローダウンを引き起こす1つの状況は、UPDATEがクラスター化インデックス内でレコードを移動させる状況だと思います。移動によってポインターが変更されるかどうか、またはポインターがクラスター化インデックスへの単なるKEY値であるかどうかはまだわかりません。レコード値を取得します。
-Jmoney38

回答:


6

インデックス化されていない列を更新しても、インデックスは変更されません。単純な場合、テーブルへの全体的な影響もありません。

クエリがインデックスを使用してデータを検索できる場合、検索高速になりますが、正確な動作(SQLブランドによって異なる)は他のブランドのSQLとは異なる場合があります。(主にMicrosoft SQL Serverを使用しています。)

もちろん、データ量を大幅に増やして列を更新すると、行が別のページに移動する場合があります。


1
OPにSQL Serverが記載されているので、タグを追加したので、SQL Server
Tom V-Team Monica

10

比較的高速な最新のシステムの場合、OLTPテーブルへの単一のインデックスの追加は、おそらくシステムの大部分のパフォーマンスの観点から事実上検出できません。。ただし、不要なインデックスを作成することはできません。また、おそらくテーブルのすべての列に単一列のインデックスを作成しないでください。

多くのクエリで有用なインデックスが存在すると、非常に顕著な速度の改善がもたらされるという仮定は正しいです。

あなたの質問はパフォーマンスに関するもののように見えますが、インデックスの追加に関する他の潜在的な問題がいくつかあります。

  1. インデックスの作成に必要な時間は、インデックスがテーブルに追加されている間、ブロックされる可能性があります。ロックの寿命は非常に短く、ほとんどの場合、大きな問題は発生しません。

  2. インデックスの変更により、基礎となるテーブルを参照するプランの実行プランが無効になります。これらの実行計画を再コンパイルすると、一部のクエリのパフォーマンスが低下する場合があります。

  3. インデックスを変更すると、以前に何も返されなかったエラーを返すクエリが発生する場合があります。varcharフィールドに含まれる日付を返すために使用されたフィルター選択されたインデックスの場合を考えてみましょう。フィルターが日付以外の行を削除し、そのフィルターが後で変更された場合、日付以外のデータを変換しようとすると、そのインデックスに依存するクエリが失敗する可能性があります。

  4. 新しいインデックスにより、実行順序が変更され、以前は発生していなかった場所でデッドロックが発生する可能性があります。


「インデックスが影響を受けない場合に更新に必要なコードパスを評価する必要があります」これは事実ではありません。コンパイル/最適化フェーズでは、更新する必要があるインデックスがあればそれを非常によく知っており、それに応じてプランを作成します。インデックス(INCLUDEおよびクラスター化キー列を含む)の列を変更(SETリストで宣言)しないUPDATEステートメントは、そのインデックスを更新する必要がなく、実行フェーズもそれに触れません。DELETEとINSERTは明らかにすべての列に(論理的に)触れ、すべてのインデックスを更新する必要があります。
レムスルサヌ16年

@RemusRusanuしかし、更新する必要がある行を見つけるためにインデックスを使用できる場合、評価する必要はありませんか?
トムV-チームモニカ

@RemusRusanu-QOが計画をコンパイルすると、CPUは不要になると思います。ただし、計画をコンパイルするには、それを行う必要があります。計画が頻繁にコンパイルされる場合、わずかな違いが生じる可能性があります。
マックスヴァーノン

インデックスを使用して削除/更新候補行を見つける @TomV は、まったく異なるトピックです。その場合、インデックスを介して行を検索することの利点は、インデックスメンテナンスコストの問題を克服するはずです。
レムスルサヌ

@MaxVernon DMLの頻繁な再コンパイル(UPDATE)の有効なシナリオはないと主張します。アドホッククエリの有効な(避けられない?)再コンパイルのためにいくつかのケースを購入します。しかし、DML?どのようなアプリがアドホックでユニークなUPDATEステートメントを作成できますか?DMLを頻繁に再コンパイルすると、「Parameterize me」と大声で叫びます。
レムスルサヌ

-2

更新操作が固定サイズ(整数など)の非インデックス列を対象とする場合、一般的に遅くなることはありませんが、選択ステートメントと比較すると、最終的には遅いディスクにも更新を書き込む必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.