web-dev-qa-db-ja.com

悪いインデックスの定義は何ですか?どうやって決めるの?どんな論理が必要ですか?

悪いインデックスを見つけるインターネット上のクエリがあります

彼らの論理はとても簡単ですが

書き込み数>読み取り数=不良インデックスの場合

ここで1つのクエリ例

    SELECT  OBJECT_NAME(s.object_id) AS 'Table Name',
        i.name AS 'Index Name',
        i.index_id,
        user_updates AS 'Total Writes',
        user_seeks + user_scans + user_lookups AS 'Total Reads',
        user_updates - ( user_seeks + user_scans + user_lookups ) AS 'Difference'
FROM    sys.dm_db_index_usage_stats AS s WITH ( NOLOCK )
        INNER JOIN sys.indexes AS i WITH ( NOLOCK ) ON s.object_id = i.object_id
                                                       AND i.index_id = s.index_id
WHERE   OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1
        AND s.database_id = DB_ID()
        AND user_updates > ( user_seeks + user_scans + user_lookups )
        AND i.index_id > 1
ORDER BY 'Difference' DESC,
        'Total Writes' DESC,
        'Total Reads' ASC ;
-- Index Read/Write stats for a single table
SELECT  OBJECT_NAME(s.object_id) AS 'TableName',
        i.name AS 'IndexName',
        i.index_id,
        SUM(user_seeks) AS 'User Seeks',
        SUM(user_scans) AS 'User Scans',
        SUM(user_lookups) AS 'User Lookups',
        SUM(user_seeks + user_scans + user_lookups) AS 'Total Reads',
        SUM(user_updates) AS 'Total Writes'
FROM    sys.dm_db_index_usage_stats AS s
        INNER JOIN sys.indexes AS i ON s.object_id = i.object_id
                                       AND i.index_id = s.index_id
WHERE   OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1
        AND s.database_id = DB_ID()
        AND OBJECT_NAME(s.object_id) = 'AccountTransaction'
GROUP BY OBJECT_NAME(s.object_id),
        i.name,
        i.index_id
ORDER BY 'Total Writes' DESC,
        'Total Reads' DESC ;,

しかし、問題はこれで簡単ですか?すべての書き込みを呼び出すことができます>読み取り=悪いインデックス?

不正なインデックスを定義できるSQLクエリを持つより良いロジックはありますか?

一意制約などのデータの整合性を保証するインデックスを無視します

インデックスが毎分更新され使用されると仮定しましょう

SQL Server 2014を使用していますが、ここでこのクエリが生成する結果

タイ

enter image description here

2
MonsterMMORPG

しかし、問題はこれで簡単ですか?

絶対違う。残念ながら、それはアプリケーション間で大きく異なる可能性があるため、「使用されないインデックスは無駄である」以外は、それらのどれも普遍的に適用できるとは言えないような「経験則」がたくさんあります。

すべての書き込みを呼び出すことができます>読み取り=悪いインデックス?

そのインデックスが整合性を適用するためのものである場合(つまり、一意のインデックスであるか、外部キーをサポートしている場合)、その事実は一般にパフォーマンス要件を上回ります。また、書き込みはほとんど問題にならない場合もあります(深夜の一括更新など)または本当に重要なことは、これらの読み取りが可能な限り高速であるため、低速の書き込みは支払う価値のある代償です。

これらの問題について考えるときは、常に、あなたが見ている数字がカバーする期間を考慮してください。今週はインデックスが十分に使用されていないように見えるかもしれませんが、次の週は新しいレポート期間の始まりなので、ユーザーはさまざまなアクションを実行しており、インデックスは突然はるかに有用に見えます。

経験則を生きるのが難しくて速い規則として決して使用しないでください。それらを提案として使用し、特定のアプリケーションのニーズを理解した上で結果を慎重に検討してください。

答えを広げて、詳細を追加できますか?

より具体的な質問がない限り、本全体を書くことなしに、これは非常に広い分野です。実際、多くの本全体がこの主題について書かれています... http://use-the-index-luke.com/ から始めるのが良いでしょう。

5
David Spillett

絶対的な論理はありません。私の言葉では、良いインデックスを定義するには

「インデックスがクエリを高速化して高速化する場合、それは優れたインデックスであり、そのインデックスを保持できます。」.

あなたは sp_blitzindex を使用しており、未使用のインデックスと不良インデックスを指摘します。また、 Jason Stratesインデックス分析スクリプト もあるので便利です。上記のどちらでもうまくいくと思います。しかし、あなたが他のアプローチが好きなら、以下は私が時々従うものです。

再グレードuser readsおよびuser writesインデックスが適切に利用されているかどうかを判断できる絶対値はありません。しかし、実際に行うのは、ユーザーの読み取りをユーザーの書き込みで割り、100を掛けてパーセンテージを取得することです。

注:これは常に当てはまりません。「タイブレーカー」として使用します。

  1. パーセンテージが60より大きい場合、そのインデックスを維持できます
  2. パーセンテージが50〜60の場合、このインデックスが役立つかどうかを自分で判断する必要があります。
  3. それが50未満の場合、インデックスは、クエリの高速化に役立つよりも、更新でのI/O使用率を高めます。
  4. 20〜30%程度の場合は、まず無効にしてから削除できます。

例:

見る index bまったく使えません。最初に無効にしてから削除するのが正しい判断です。

見る index aインデックスは読み取りも更新もされていますが、読み取り以上に更新されています。除算値は.80で、ほぼ80%です。このインデックスは、使用と更新の両方で保持できます。このインデックスに問題はありません。

見る index C除算は.33の値を与え、パーセンテージは33%です。このインデックスは、これが良いことをしているよりももっと害を与えていることをもう一度調べなければなりません。

パーセンテージに関する全体的な考え方は、データベースについての知識の深さに基づいています。インデックスを保持するか削除するかの決定は、主に要件に基づく必要があります。そのかなり可能性のあるインデックスは、隔週または毎週利用されるかもしれませんが、毎日更新されます。これは、ジョブが毎週または2週間ごとに実行され、それらのインデックスをその時点でのみ使用するためと考えられます。

さらに、ページ数が2000未満の小さなインデックスについて心配する必要はありません。これも球場図です。このようなインデックスは害を及ぼすことはありません。

3
Shanky