2

2 つのインデックスを持つテーブルがあります。1 つは、3 列の複数列クラスター化インデックスです。

(
   symbolid int16,
   bartime int32,
   typeid int8
) 

2 つ目はクラスタ化されていない

(
   bartime int16
)

私が実行しようとしている選択ステートメントは次のとおりです。

    SELECT symbolID, vTrdBuy
    FROM mvTrdHidUhd 
    WHERE typeID = 1 
    AND barDateTime = 44991 
    AND symbolid in (1010,1020,1030,1040,1050,1060) 

SQL Management Studioエディターを使用してsql2008でこのクエリを実行し、実際の実行計画を有効にすると、SQLが2番目のインデックスと提案を使用して、3つの列(symbolid、bartime、typeid)の新しいインデックスを作成することがわかりましたが、クラスター化されていません!!! (すでにクラスター化されたインデックスがあるため、非クラスター化インデックスと言っていると思います)

この選択は間違っています。もう一度同じクエリを再実行し、SQL にクラスタ化されたインデックス ("with index" を使用) を使用させると、パフォーマンスが向上します。

ここで 2 つの質問があります。1 つはこの動作に関連し、もう 1 つはクエリ自体に関するものです。

  1. SQL が間違ったインデックスを選択し、同じインデックスを提案する理由
  2. "where"パフォーマンスを向上させるために、条件でどちらを使用する必要がありますか

(1010,1020,1030,1040,1050,1060) のシンボル ID

(symbolid = 1010 または symbolid = 1020 など)

((1010 と 1060) の間の記号)

テスト後

where 条件を IN の使用から >= および <= の使用に変更すると、bartime 列の非クラスター化インデックスは、3 列のクラスター化インデックスよりも優れたパフォーマンスを発揮することがわかりました。

SO WHERE が IN を使用する場合、クラスター化インデックスを使用する方が良い場合が 2 つあります。

4

6 に答える 6

3
SELECT  symbolID, vTrdBuy
FROM    mvTrdHidUhd 
WHERE   typeID = 1 
        AND barDateTime = 44991 
        AND symbolid IN (1010,1020,1030,1040,1050,1060)

この条件は、クラスター化インデックスの単一の連続した範囲ではカバーされません。

これらの行:

1010, 44991, 1
1010, 50000, 1
1020, 44991, 1

はインデックスで順番に表示されますが、クエリは 1 番目と 3 番目のものを選択し、2 番目をスキップします。

SQL ServerClustered Index Seekあなたの場合のように、述語の数が限られている場合に使用できますIN。この場合、いくつかの範囲を使用します。

SELECT  symbolID, vTrdBuy
FROM    mvTrdHidUhd 
WHERE   (typeID = 1 
        AND barDateTime = 44991 
        AND symbolid = 1010)
        OR
        (typeID = 1 
        AND barDateTime = 44991 
        AND symbolid = 1010)
        OR …

しかし、BETWEEN範囲の場合symbolid、限られた数の述語を構築できないため、効率が低下しますClustered Index Scan(スキャンしsymbolidて間違った結果を除外するだけです)。

この場合、非クラスター化インデックスのパフォーマンスが向上します。

クエリを次のように書き直すことができます。

SELECT  symbolID, vTrdBuy
FROM    (
        SELECT  DISTINCT symbolid
        FROM    mvTrdHidUhd 
        WHERE   symbolid BETWEEN 1010 AND 1050
        ) s
JOIN    mvTrdHidUhd m
ON      m.symbolid = s.symbolid
        AND m.typeID = 1 
        AND m.barDateTime = 44991

Clustered Index Seekのリストを作成し、このリストに参加するために、テーブルでも使用しますDISTINCT symbolid

于 2009-06-03T16:15:49.100 に答える
0

インデックス列の順序が、オプティマイザーがインデックスを選択するかどうかに影響する可能性があります。インデックスが (symbolid int16,bartime int32,typeid int8) であることを示していますが、symbolid は where 句で最も異なる値です。これには、6 つの値に対して 6 つのインデックス ルックアップが必要です。

私はおそらく between ステートメントから始めますが、データ、サーバー、インデックスなどでテストするだけで、最良のケースが証明されます。

別のインデックスを作成する場合は、それらの列に対して他の 2 つの順序を試してください。

そして、他の場所で述べたように、統計を更新してください

于 2009-05-18T07:48:14.083 に答える
0

テーブル/インデックスの統計を更新すると、正しいインデックスが選択される場合があります

于 2009-05-18T07:42:26.667 に答える
0

symbolid BETWEEN 1010 AND 1050可能であれば使用してください。BETWEENまたは=または>=または>または<n または<=または これらの組み合わせを使用すると、通常、またはANDを使用するよりもパフォーマンスが向上し、インデックスの選択も向上します。ORIN

于 2009-05-18T07:44:51.750 に答える
0

(symbolid,bartime,typeid,mvTrdBuy) のカバリング インデックスを試すこともできます。

于 2009-05-19T13:26:00.400 に答える