最初からインデックスを作成するか、パフォーマンスの問題が発生したとき?


15

私の質問は、インデックスの使用に関するものです。

  1. 最初から、またはパフォーマンスの問題が発生したときに、インデックス作成を開始する必要がありますか?

  2. クエリの実行中に一時インデックスを作成することもできます。そのような技術の長所と短所は何ですか?

回答:


17

最初からインデックス作成を開始する必要がありますか、それともパフォーマンスの問題が発生したときですか?

インデックス作成戦略は、使用パターンが出現するにつれて進化する傾向があります。ただし、事前に適用できる戦略と設計ガイドラインもあります。

  • 適切なクラスタリングキーを選択します。通常、テーブルへの挿入の予想パターンに基づいて、設計時に適切なクラスター化インデックスを決定できます。将来の変化のために説得力のあるケースが出現した場合は、そうしてください。

  • プライマリおよびその他の一意の制約を作成します。これらは一意のインデックスによって実施されます。

  • 外部キーと関連する非クラスター化インデックスを作成します。外部キーは最も頻繁に参照される結合列なので、最初からインデックスを付けます。

  • 明らかに高度に選択的なクエリのインデックスを作成します。クエリパターンについては、非常に選択的であり、スキャンではなくルックアップを使用する可能性が高いことが既にわかっています。

上記を超えて、新しいインデックスを実装するために段階的かつ全体的なアプローチを取ります。全体として、追加を評価するときに、すべてのクエリと既存のインデックスに対する潜在的な利点と影響を評価することを意味します。

SQL Serverサークルで珍しいことではない問題は、インデックスDMVとSSMSのヒントが欠落していることからのガイダンスの結果としてのインデックスの過剰作成です。これらのツールはどちらも既存のインデックスを評価せず、既存の5列のインデックスに単一の列を追加するのではなく、新しい6列のインデックスを作成することをお勧めします。

-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
)

-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

Kimberly Trippには、インデックス作成戦略に関する優れた資料があり、SQLに焦点を当てている間は他のプラットフォームにも適用できます。SQL Serverユーザーには、上記の例のような重複を識別するための便利なツールがいくつかあります。

クエリの実行中に一時インデックスを作成することもできます。そのような技術の長所と短所は何ですか?

これは通常、めったに実行されないクエリ、通常はETLにのみ適用されます。以下を評価する必要があります。

  1. インデックスの作成にかかる時間がクエリの実行時間を短縮しますか。
  2. インデックスを適切な場所に残すメンテナンスのオーバーヘッドは、必要なときに作成/削除するのにかかる時間を上回っていますか。

3
+1クラスタリングキー、外部キー、一意/プライマリキー、および額面価格で欠落しているインデックスDMVを信頼しない...これらのすべては素晴らしいアドバイスです。SQL Serverの既存のインデックスの処理は、sys.dm_db_index_usage_stats DMVを使用して簡単に監視できます。一定の期間にわたって、スキャンまたはシークされていないインデックスを一覧表示しながら、これらの同じインデックスが複数回更新されていることを確認できます。これはオーバーインデックスを示しています。
マットM

1
+1、ただし、「明らかに高度に選択的なクエリのインデックスを作成します。」他のすべてのシナリオをカバーしていません。インデックスは、クエリの選択性が高くない場合でも、結果の並べ替えに役立ちます。また、選択したすべての列をカバーする場合、クエリを高速化できます。
不合理

1
同意したが、質問は終盤ではなく出発点を探していた。すべてをカバーすることはめったにないため、使用パターンなしではカバーするクエリを特定することは困難です。
マークストーリースミス

8

両方のアプローチに関連するリスクは本当にあります。

オプションa)最初からインデックスを作成しますが、使用されていないインデックスを多数作成したことに気付いていません。これらはオーバーヘッドを追加します(データを変更するクエリに最も顕著ですが、最適なインデックスを特定しようとするSELECTステートメントの最適化も伴います)。

使用されなくなったインデックスを特定し、それらを削除しようとするためにあなた自身を鍛える必要があります(PostgreSQLはこれを行うことができます;残念ながら、MySQLは比較して非常に弱いです。)

オプションb)苦情が始まるまでインデックスを追加しないでください。または、特定のクエリが遅くなり改善できる可能性があることを診断ツールがトリガーします。

導入するリスクは、インデックスが必要であることに気付いてから追加するまでの間に十分な時間枠がないことです。

PostgreSQLはCONCURRENTLY、インデックスの構築をサポートします。これにより、この突発的なインデックスの追加要件から生じるストレスの一部が軽減されますが、マニュアルには注意事項いくつかあります。


オプション(b)が私の好みになる傾向がありますが、両方のオプションのハイブリッドがおそらく最良のソリューションだと思います。それは、インデックスが実際に使用されると思うかどうかに関するあなたの信頼レベルに関係しています。

これを特に複雑な議論にしているのは、通常、インデックスを変更するのは簡単ですが、スキーマを変更するのは難しいということです。b の遅延反応を無謀な言い訳として宣伝したくありません。


4

マークの答えに加えて

予想される量で現実的なテストデータを取得することで、感覚をつかむことができます。クエリが1000行で問題なく実行され、実稼働では100万行ではない、非常に多くの(多すぎる)ケースを見てきました。

可能であれば、後で本番のコピーを作成し、

もちろん、私は奇妙な問題だけを見てきました他のすべてが同じである場合の使用パターンのために、本番で

一時的なインデックス?ETLロードパターン以外で、一度必要になった場合は再度必要になります。忘れないでください:インデックスの作成/削除は書き込みであり、ログに記録されます=より多くの負荷


3

いくつか追加するだけです。

  • 一時インデックスはひどいアイデアです。インデックスが一時テーブル上にない限り。
  • インデックスは、人々が認識するよりもはるかに多くのデータスペース(およびその他のオーバーヘッド)を占有します。したがって、それらを控えめに作成します。

これが私のアプローチです。

  1. マークと同様に、意味のある場所でインデックスを作成しますが、期限を過ぎないでください。
  2. 新しいインデックスを作成するためにパフォーマンスが低下するまで待つ必要はありません。新しいSQLを作成するたびに、クエリプランを実行します(prodデータベースに対して実行することが望ましい)。新しいインデックスが必要かどうかを確認できるはずです。
  3. 未使用列のwhere句を入れ> 0たり> ""、配置することを恐れないでください。

    1. つまり、A、B、C、およびDのインデックスがあるとしましょう。ただし、A、B、Dの情報しかありません。できない理由はありません
    select * from blah 
    where A="one" 
    and B="two" 
    and C>=""     --to match index
    and D="four"
    
    --This will use your existing index. No need to create a redundant one.

もう1つ、これは「dba」フォーラムにありますが、インデックスの作成は、dbaではなく開発者の責任である必要があります。(それらが完全に分離している場合。)
user606723

2
インデックスが占有するスペースに関する説明は少し誤解を招きやすく、非クラスター化インデックスのオーバーヘッドはほとんどありません。その点について質問を投稿できる場合は、さらに調査する価値があります。第二に、インデックスの作成が開発者のドメインであることに同意しません。開発者とDBAの間のコラボレーションが最良の結果を生むことができる分野の1つです。
マークストーリースミス

1
私たちのテーブルの例を紹介します。テーブルサイズ:21052404 KB。このテーブルの1つの非クラスター化インデックスのサイズ:6637470 KB。オーバーヘッドはほとんどありませんか?私はそうは思いません。さらに、私はDBAと協力すべきではなく、新しいインデックスを作成する必要があるかどうかを判断するのは開発者の責任であるべきだと言っています。彼らはSQLを書くべきではなく、dbasが自分でこれを理解することを期待すべきではありません。
user606723

1
コンテキストなしでは、そのような数字を引用することはできません。NCインデックス列とクラスター化キーを指定しないと、オーバーヘッドとデータの割合を計算することはできません。
マークストーリースミス

Touche。キーは[numeric(24)、char、date]であり、NC列は[date、numeric(24)]です。(この特定のインデックスの2列だけです)。
-user606723

2

最初の質問だけに答えようとします。一定時間後にテーブルにいくつのレコードがあるかを最初から大まかに推定できる場合は、最初からインデックスを設計することをお勧めします。最も頻繁に使用されると思われるアプリケーション呼び出しに対して、できるだけ多くの呼び出しを自動化するテストツールまたはテストスクリプトを使用してみてください。最初から回避できるテーブルスキャンがわかります。

最初は推測作業ですが、やがて、適切な使用統計があるので、より鮮明な画像が得られます。

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