2012-03-30 3 views
-2
select 
    a.Transport_Mode, sum(a.Inv_Qty) 
from 
    dbo.DespSum_Year a, dbo.Item_Master b 
where 
    a.Inv_Date between '2011-04-01' and '2012-03-31' 
    and a.item_name = b.itemcode 
group by 
    a.Transport_Mode 

despsum_yearには1000万行、Inv_dateには非クラスタ化インデックスがあります。SQL Serverはいつインデックススキャンを選択しますか?

上記のクエリを実行しているときに、テーブルスキャンを使用していることがわかります。インデックススキャンを使用してクエリを作成する方法を教えてもらえますか?

+0

スキーマ?どのテーブルに何が入っているかわからない。 –

+1

テーブルスキャンには**ヒープ**が表示されます - クラスタ化インデックスはありません。 **最初の**を修正してください。次に、 'item_'と' item_code'と同様に 'inv_date'と、おそらく' transport_mode'の両方にインデックスを持たせる必要があります。 –

+1

@marc_s:OPはそれをとてもうっかり隠しましたが、これはJoin ... 'From DespSum_Year、Item_Master'ですので、各テーブルの詳細が必要です。 – MatBailie

答えて

2

クエリには、ソートされたテーブルを必要とする3つの部分があります。
1. JOIN
2.他の人がより重要とみなされているためGROUP BY

あなたのクエリがインデックスを使用していないWHERE
3。他のフィールドにインデックスを置き、必要に応じてインデックスを合成します。

私は詳細を述べますが、残念ながらあなたのクエリはどのフィールドがどのテーブルに属しているのかを言いません。 フル詳細については、各表のスキーマと索引の詳細を記載してください。

もう少しデータの振る舞いが分かっていればいいと思います.Transport_Modeでgoupingすると、いくつかの大きなグループまたは小さなグループが生成されますか? 1つのテーブル内でitem_name/itemcodeは一意のキーですか?クエリのフィールドにテーブルを追加するなど、など


EDIT

感謝。データについてもっと知らなくてもまだかなり制限がありますが、私はあなたを助けようとします。


1)。あなたがこれはあなたがいずれかのフィルタ(1:0..1)のいずれかとし、それを使用していることを意味し、あなたのSELECTGROUP BY

Item_Masterを使用していないに、または乗数(1:1..many) 、または両方(1:0..many)。

私はこれをフィルタとして使用するとします。


2)。あなたは、私がInv_DateがDATETIMEであるとは時間の部分を持っていないと仮定しますInv_Date

をフィルタリングするBETWEENを使用。それはいつも真夜中である - 日付のみを表す。あなたに366の日付を与える(うるう年)。一緒


これらのあなたは第三で2列グループでフィルタするテーブルを有することを意味します。最終結果を与えるために最小限の努力をするために、これらのフィールドをソートする順序を決定する必要があります。

は6つの可能性...

1). Transport_Mode => Item_Name  => Inv_Date 
2). Transport_Mode => Inv_Date  => Item_Name 
3). Item_Name  => Transport_Mode => Inv_Date 
4). Item_Name  => Inv_Date  => Transport_Mode 
5). Inv_Date  => Transport_Mode => Item_Name 
6). Inv_Date  => Item_Name  => Transport_Mode 

あなたが最初Transport_Modeを持っている場合、それはあなたのGROUP BYに非常に友好的だがあります。すべての可能なモードは、並べ替えなしで集約できるように事前にグループ分けされます。次に、各グループに対して、レコードをフィルタリングするだけで、をフィルタリングする場合はItem_NameBETWEENをフィルタリングする場合はInv_Dateとなります。

したがって、(Transport_Mode, Item_Name, Inv_Date)のカバー指数は私にとってはよかったようです。

しかし、これは、クエリがカバーする363の値がInv_Dateであることが原因の一部です。あなたが一日中のみ興味を持っていた場合、(Inv_Date, Transport_Mode, Item_Name)

を持っている方が良いでしょう。しかし、あなたがTransport_Modeでは非常に少数の値とItem_Nameの多くの、多くの価値を持っている場合は、多分あなたはあなたのインデックスにTransport_ModeItem_Nameを持つの恩恵を受けるだろうか?

データの詳細がない場合は、6つのインデックスをすべて作成し、実際の状況を表すためにテーブルを作成してください(まだない場合)。次にクエリを実行してください。実行計画をチェックすると、オプティマイザがどのインデックスを優先しているかを見ることができます。

また、異なるインデックスと実行計画を使用するため、一度に1つずつ作成してクエリをプロファイルします。それで、最も有用であるものを、ただ1つではなく、すべてのクエリにわたって保持することができます。


しかし、すべての場合には、確認してくださいあなたにもItem_Masterテーブル上のインデックスitemcode

+0

私の理解のために与えられた非常に優れた詳細な答えです。ありがとう。 –

1

多くの要因によって異なります。クエリヒントを使用してインデックスを強制的に使用し、実行計画(特に、主キーの見積もりの​​行数とコスト)を比較することができます。日付条件の選択性とは何ですか?一般的にこのクエリ(実際にはデータ構造に依存しますが、前提として)では(item_name、Transport_Mode)のインデックスがうまく機能します。

+1

OPはそれを非常にうまく隠しましたこれは結合です... 'DespSum_Year、Item_Master' – MatBailie

関連する問題