41

できるだけ早くデータを検索して取得できるようにしたい SQL Server データベースにテーブルがあります。テーブルへの挿入にかかる時間は気にしません。データを取得できる速度だけに関心があります。

問題は、テーブルが 20 種類以上の異なるクエリでアクセスされることです。これにより、クエリごとに特別に設計されたインデックスを追加するのは面倒な作業になります。代わりに、テーブルのすべての列を含むインデックスを追加することを検討しています。これは、「優れた」データベース設計では通常行うことではないため、そうすべきではない正当な理由があると思います。

なぜ私がこれをしてはいけないのか誰か教えてもらえますか?

更新:言及するのを忘れていましたが、データベースのサイズも気にしません。データベースのサイズが必要以上に大きくなっても問題ありません

4

8 に答える 8

84

まず、SQL Server のインデックスは、そのインデックス エントリに最大 900 バイトしか含めることができません。それだけでは、すべての列でインデックスを作成することはできません。

何よりも、そのようなインデックスはまったく意味がありません。何を達成しようとしていますか??

これを考慮してください: にインデックスがある場合(LastName, FirstName, Street, City)、そのインデックスを使用してクエリを高速化することはできません

  • FirstName1人
  • City
  • Street

そのインデックスは、次の検索に役立ちます

  • (LastName)、 また
  • (LastName, FirstName)、 また
  • (LastName, FirstName, Street)、 また
  • (LastName, FirstName, Street, City)

しかし、実際には他には何もありません - 確かに justStreetまたは just City!を検索する場合はそうではありません。

インデックス内の列の順序によってかなりの違いが生じます。クエリ オプティマイザーは、インデックスの途中にある列だけをルックアップに使用することはできません。

電話帳を考えてみてください。おそらく、LastName、FirstName、Street の順です。では、その索引付けは、あなたの街のすべての「Joe's」を見つけるのに役立ちますか? 「メインストリート」に住むすべての人?? いいえ - 最初に LastName で検索できます - 次に、そのデータセット内でより具体的に取得します。すべてに索引を付けるだけでは、すべての列の検索を高速化するのにはまったく役立ちません。

検索できるようにしたい場合はStreet、別のインデックスを追加する必要があります(Street)(そして、意味のあるもう1つまたは2つの列)。

または他のもので検索できるようにしたい場合はOccupation、そのために別の特定のインデックスが必要です。

列がインデックスに存在するからといって、その列のすべての検索が高速化されるわけではありません!

主なルールは、できるだけ少ないインデックスを使用することです。インデックスが多すぎると、インデックスがまったくない場合よりもシステムにとってさらに悪いことがあります.... システムを構築し、そのパフォーマンスを監視し、最もコストのかかるクエリを見つけます。インデックスを追加するなどして、これらを最適化します。

できるという理由だけですべての列にやみくもにインデックスを付けないでください-これはシステムパフォーマンスの低下を保証するものです-インデックスにはメンテナンスと維持も必要です.これらすべてのインデックスを更新する必要があるためです。

于 2011-03-27T08:28:23.277 に答える
11

インデックスの仕組みを根本的に誤解しています。

この説明「マルチカラム インデックスの仕組み」をお読みください。

次に疑問に思うのは、列ごとに 1 つのインデックスを作成しない理由です。ただし、最高の選択パフォーマンスに到達しようとすると、これも行き止まりになります。

面倒くさいと思われるかもしれませんが、丁寧に索引を付けるには必須の作業だと思います。この例のように、ずさんなインデックス作成は反撃します。

注: 適切なインデックス作成が有効であると強く確信しており、多くの人があなたとまったく同じ質問をしていることを知っています. だからこそ、私はそれについての無料の本を書いています。上記のリンクは、質問への回答に役立つ可能性のあるページを参照しています。ただし、最初から読みたい場合もあります。

于 2011-03-27T09:46:07.377 に答える
2

...すべての列を含むインデックスを追加し、クエリが実際にそのインデックスを使用できた場合、主キーの順序でスキャンします。つまり、ほぼすべての記録を達成しています。平均検索時間は O(n/2).. 実際のデータベースにヒットするのと同じです。

インデックスについて少し読む必要があります。

テーブルのインデックスを C# のディクショナリに少し似ていると考えると役立つ場合があります。

var nameIndex = new Dictionary<String, List<int>>();

これは、name 列がインデックス化され、主キーのリストを返すことを意味します。

var nameOccupationIndex = new Dictionary<String, List<Dictionary<String, List<int>>>>();

つまり、名前列 + 職業列が索引付けされます。ここで、インデックスに 10 個の異なる列が含まれ、非常に深くネストされ、テーブル内のすべての行が含まれているとします。

これは正確にどのように機能するかではありません。しかし、C# で実装された場合にインデックスがどのように機能するかについてのアイデアが得られるはずです。行う必要があるのは、広範囲にクエリされる 1 つまたは 2 つのキーに基づいてインデックスを作成し、テーブル全体をスキャンするよりもインデックスが役立つようにすることです。

于 2011-03-27T08:19:29.273 に答える
2

これが、クエリが READ クエリ用に高度に最適化されているデータ ウェアハウス タイプの操作であり、データを分析する方法が 20 ある場合、たとえば、

WHERE 句に含まれる..

 Q1: status, type, customer
 Q2: price, customer, band
 Q3: sale_month, band, type, status
 Q4: customer
 etc

そして、あなたは絶対に十分な高速ストレージスペースを持っているので、必ずすべての単一列のインデックスを個別に作成してください。したがって、20 列のテーブルには、個々の列ごとに 1 つずつ、合計 20 のインデックスがあります。おそらく、ビット列またはカーディナリティの低い列を無視するように言うことができますが、ここまで進んでいるので、(その警告で) 気にする必要はありません。彼らはただそこに座って WRITE 時間をかき回すだけですが、全体像のその部分を気にしなければ、問題ありません。

20 個のクエリを分析します。ホット クエリ (最もホットなクエリ) がまだ高速化されていない場合は、クエリ ウィンドウで 1 つのクエリを使用して SSMS (Ctrl-L を押す) を使用して計画します。そのクエリに役立つインデックスを教えてくれます。作成するだけです。それらをすべて作成します。これにより、書き込みコスト、バックアップファイルのサイズ、データベースのメンテナンス時間などが再び増加することを十分に覚えておいてください。

于 2011-03-27T10:55:31.067 に答える
1

代わりに、テーブルのすべての列を含むインデックスを追加することを検討しています。

これは常に悪い考えです。データベースのインデックスは、魔法のように機能するある種の妖精の粉ではありません。クエリを分析し、クエリの対象と方法に応じて、インデックスを追加する必要があります。

「インデックスにすべてを追加して仮眠をとる」という単純なものではありません

于 2011-03-27T08:18:41.243 に答える
0

1)サイズ、インデックスは基本的に、その列にデータのコピーを作成します。バイナリツリーのような簡単に検索できる構造です(SQL Serverの仕様はわかりません)。2)速度について言及しましたが、インデックス構造は追加が遅くなります。

于 2011-03-27T08:19:36.373 に答える
-1

そのインデックスは、テーブルとまったく同じになります (別の順序でソートされる可能性があります)。
クエリの速度は向上しません。

于 2011-03-27T08:18:56.373 に答える