web-dev-qa-db-ja.com

SQL Server 2005でインデックススキャンを回避する方法

Cell_IDCellCellValueなどの列があるCellRowという名前のテーブルがあります。

Cellrowの最大値は1〜5です。Cell_IDフィールドにはクラスター化インデックスがあります。このテーブルには100000行が含まれています。

私のクエリでは、CellRowフィールドからデータを取得するために、CellRow > 3のようなWHERE句でCellValue列を使用する必要があります。問題は、このように実行すると、クエリが非常に遅くなるのは常にテーブルスキャンであるということです。

また、CellRowフィールドに非クラスター化インデックスを配置してチェックしましたが、CellRowフィールドにはそれほど多くの値がなく、毎回1〜5個しかありません。 where句でCellIDを使用できません。

私は私のクエリで多くのテーブルを使用しています

Table_1はクラスター化インデックス列を使用してtable_2と結合しており、table 2は非クラスター化インデックス列を使用してtable_3と結合しており、table_3Cellテーブルと結合しています非クラスター化インデックスを使用する。

結局のところ、セルテーブルを含むすべてのテーブルから異なる値を取得していますが、WHERE句でCellRowフィールドを使用すると、インデックススキャンを取得しています。

任意のソリューション:)

どうもありがとうございます!

4
user999896

任意のソリューション:)

いいえ、そうではありません。

あなたが言ったように-CellRowはあまり選択的ではありません-5つの可能な値、100'000行=可能な各値のおよそ20'000行。

SQL Serverのクエリオプティマイザーはこれを認識し、おそらく20,000行のシークよりもインデックススキャンを実行する方が簡単で効率的であると考えています。

これを回避する唯一の方法は、より選択的なインデックス、つまり、2%、3%、または最大を選択する他の列を使用することです。各クエリの行の5%。

PS:実行計画を確認してください-インデックスから直接値を取得しますか、それともデータを取得するために「キー検索」ステップが必要ですか?

列のデータ型については言及していませんでした。CellValueが大きすぎない場合は、インデックスに追加して(または少なくともインデックスに含めることで)、コストのかかるキールックアップを回避できます。

CREATE INDEX IX_CellRow_CellValues
ON dbo.Cell(CellRow) INCLUDE(CellValue)

ただし、インデックススキャンは引き続き可能です。

11
marc_s

cellrowにインデックスを作成しますが、値が5つしかない場合、オプティマイザはそれを使用しないと決定する可能性がありますが、3を超える値がまれであることがわかっている場合、クエリにヒントを追加して、エンジンがそのインデックスを使用するようにすることができます。
編集:別のテーブルでセル行を分離し、セル行4と5のテーブルの結合であるビューを作成して、そのビューでクエリを実行することで、動作するかどうかわからない別のより複雑なソリューションがあります。 、インデックスは使用しませんが、関連するレコードをトラバースするだけです。これは、データディクショナリが行うことの一種ですが、メンテナンスが増えるため(たとえば、データが3から4に変更され、1回の更新ではなく、テーブル '3'から削除されてテーブルに挿入されるため)、注意が必要ですたとえば「4」)。最終的にそれはあなたのニーズに依存します。通常、この種のことは何百万ものレコードについて話しているときに行われますが、それが自分のために行われるかどうかを試すことができます。

0
Rodolfo

私はWHERE CellRow in (4, 5)WHERE CellRow > 3よりもうまく機能することを期待します。 ----

0