4

数億行のデータを持つテーブルがあります。EventId整数フィールドであると呼ばれるフィールドがあります。

特定の EventId を持つデータのみを返すさまざまなビューがいくつかあります

クエリを実行すると

SELECT TOP 1000 * FROM vw_MyView 

行を返すのに 5 分かかります。何にインデックスを追加する必要がありますか? 現在、各ビューの where 句で使用されている主キーのマスター テーブル (クラスター化LogId) と非クラスター化のインデックスがあります。EventId

ビューにインデックスを作成できることはわかっています。ビューのどのフィールドにインデックスを作成する必要がありますか? DB エンジン チューニング ウィザードを実行して、その内容を確認する必要がありますか?

フィードバックを受けて更新

内部にすべてのデータを含む私のマスターテーブルは、次のスキーマの行に沿っています

LogId (int) PK
EventId (int)
Param1 varchar(255)
Param2 varchar(255)
..
..
..
Param24 varchar(255)

各イベント タイプには異なるパラメーターがあるため、マスター テーブルの一般的なフィールド名です。

イベントの種類ごとにビューがあり、ビューを通じてマスター テーブルの ParamX フィールドに適切なフィールド名が与えられます。

したがって、1つのイベントのビューは次のようになります

SELECT LogId, Param1 AS Name, Param2 AS Address1, Param3 AS Address2
WHERE EventId = 10

クエリを実行してみました

SELECT TOP 1000 LogId from vw_MyView 

そしてそれは速く働きました。速度を落としているのは他のフィールドですが、インデックス作成が不十分であると思いますか?

更新 2 - 詳細情報

以前は、各イベントのデータは各イベントのテーブルに格納されていました。これは、新しいイベントを追加するには、イベントごとに新しいテーブルが必要になることを意味していました。

データを一時テーブルに一括インポートしてから、それをマスター テーブルに移動しています。一括インポートにより高速になりますが、マスター テーブルがこれほど大きいと、クエリが遅くなりすぎて使用できなくなるのではないかと懸念しています。

数百万行のデータは 10 年以上あるので、おそらく最初の 8 年分のデータを別のデータベースに移動して、アーカイブの目的で最新の 2 年分だけを保持することができます。

問題は、メンテナンスを必要としないが潜在的に多くのインデックス作成を必要とするマスター テーブル アプローチを続行するか、それともイベントごとにテーブルを持つ元のアプローチに戻るかということです。

フィードバックをありがとう、本当に感謝しています

4

3 に答える 3

3

通常、ビューには、多くの異なるクエリを満たすために必要な数よりも多くの列が含まれています。これらのクエリは、関連するテーブルと列のみを直接ターゲットにすることで、おそらくより効果的です。(私は 2010 年にこれについてブログを書きました。 ) あなたの場合、ビューにインデックスを付けることは役に立たないと思います...あなたが書いているクエリは、ベース テーブルのクラスター化されたインデックスではなく、そのインデックスをスキャンするだけです (そして集計を行っていないため、同じ行数になりますが、おそらくページ数は少なくなります)。より良い解決策は、基になるテーブルのインデックスを最適化することだと思います。

イベント 10 のビューに表示されたクエリを劇的に助けるはずのインデックスをお勧めします。

CREATE NONCLUSTERED INDEX Index_ForViewOnEvent10 
ON dbo.MasterTable(LogID)
INCLUDE(Param1, Param2, Param3)
WHERE EventID = 10;

このインデックスはクエリをカバーし、フィルターによってスキャンする必要がある行の数が大幅に削減されるため、これは顕著な改善になるはずです。

INCLUDE 部分の有無にかかわらず、これを試すことができます。クラスター化されたインデックスからそれらをプルするのに十分効率的かもしれません。しかし、私は上記が最良の選択肢になると思います。

さて、ここで弾道的にならないでください-以下で説明するように、100の異なるクエリを完全に満たすためにテーブルに100のインデックスを常にスローしたいわけではありません-クエリを満たすことと書き込みを行わないことの間にはバランスがあります糖蜜に。


データベース エンジン チューニング アドバイザー (DTA) について少し説明します。

このウィザードは魔法ではありません。実行して内容を確認しても害はありませんが、推奨事項をすべて取り入れて実装するだけではいけません。このツールを使用する際には、いくつかのことをお勧めします。

  • 完全なワークロードで提示するようにしてください。1 つのクエリをフィードし、その 1 つのクエリのパフォーマンスを向上させるものに基づいてインデックスを作成するように指示した場合、他のクエリがそのようなインデックスからメリットを得られない可能性があることや、他のクエリがそのインデックスからメリットを得られる可能性があることを考慮せずにインデックスを作成します。これまたは他の列がありました。
  • DTA が提供する重複に十分注意してください。先頭の 4 つのキーが同じで、末尾のキーまたは INCLUDE 列が 1 つだけ異なる 2 つまたは 3 つのインデックスを提供する場合があります。また、多くの INCLUDE 列の使用を奨励するのが好きで、これにも注意する必要があります。
  • インデックスを追加すると、DML によって実行される作業 (挿入/更新/削除) が増加するため、ワークロードのこれらの部分も念頭に置く必要があります。

DBSophicには、インデックス チューニング ウィザードよりもはるかに優れたツールがあります。これらのツールは、ワークロード全体を考慮し、冗長なインデックスを提供しません。Qure Analyzer は無料で、Qure Optimizer で利用可能な機能のサブセットを提供します。

于 2012-05-18T12:29:51.740 に答える
2

Indexed ViewsViewsを混同していると思います。もちろん、インデックス付きビューにはインデックスを含めることができます (必須です) が、SQL Server がインデックスを使用するためにインデックス付きビューを使用する必要があるという意味ではありません。インデックスを使用した方が高速であると判断された場合、通常のビューの基になるテーブルに存在するインデックスが使用されます。

そのため、ビューの SQL を調べることから始めて、どのインデックスがそのクエリの実行を高速化するのに役立つかを判断します。ビューの SQL を投稿すると、いくつかのアイデアを提案できる場合があります。

また、選択ステートメントには ORDER BY 句が含まれていないため、非決定論的クエリです。つまり、データが変更されていなくても、その後の実行で異なる結果が得られる可能性があります。

列に関しては、EventIdそれにインデックスを追加してみることができますが、役に立たない場合があります。その列のデータのカーディナリティによって異なります。

于 2012-05-18T12:20:27.847 に答える
0

「数億行のデータ」を持つテーブルにインデックス付きビューを作成しないでください。通常のビューは、データベースに格納された単なる SQL ステートメントであるため、select * from を実行するとyour_view、SQL サーバーyour_viewはその選択のために変更されます。

ビューにインデックスを付ける場合は、データベースにデータを永続化する必要があります。つまり、DB にインデックス付きの列の物理コピーを作成する必要があります。ご想像のとおり、その行数がある場合、特にその大きなテーブルを他のテーブルと結合している場合は、ストレージ サイズが大幅に増加します。

于 2012-05-18T13:45:45.513 に答える