web-dev-qa-db-ja.com

カバリングインデックスがある場合でも、パーティション化されたテーブルでのクラスター化インデックススキャン

Col1 intに基づいて分割された分割テーブルがあります。トラブルシューティングしようとしているクエリのカバリングインデックスもあります。

https://www.brentozar.com/pastetheplan/?id=BkNrNdgHm

上記は計画です

SQL Serverはテーブル全体のクラスター化インデックススキャンを実行することを決定しましたが、明らかに低速です。 (上記のプランのように)インデックスを強制すると、クエリはすばやく実行されます。

SQL Serverは、対象のインデックスが役に立たないと判断するためにどのような魔法のロジックを使用していますか? top/orderbyとrowgoalがそれと関係があるかどうかはわかりません。

私のテーブル構造は

Create table object2(col1 int, col3 datetime, col4 int, col5, col6 etc) clusterd on col1

nonclustered non aligned index is on col3,col4 (col1 is clustered so its included in nonclust)

SELECT top(?) Object1.Column1
    FROM Object2 Object1 WITH (NOLOCK,index(Column2))
    WHERE  Object1.Column3 >= ?
    AND Object1.Column4 IN (?)
    ORDER BY Object1.Column1

追加されたリポジトリを編集

    CREATE PARTITION FUNCTION [PFtest](int) AS RANGE RIGHT FOR VALUES (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000)
    GO
    CREATE PARTITION SCHEME [PStest] AS PARTITION [PFtest] all TO ([PRIMARY]);
    GO

    create table test([ID] [int] IDENTITY(1,1) NOT NULL primary key clustered,[Created] [datetime] NULL,[Type] [int] NULL,text1 varchar(10),text2 varchar(20))
    on pstest(id)
    set nocount on

    declare @a int =1
    declare @type int
    while 1=1
    begin
    if @a%30 =0
    insert into test (Created, Type, text1, text2) select getdate(),4,'four','four'
    else
    insert into test (Created, Type, text1, text2) select getdate(),1,'one','one'
    set @a=@a+1
    end
    create nonclustered index ncl1 on test(created, type)

select min(created),max(created) from test
--2018-08-02 22:46:40.187   2018-08-02 22:49:01.577
SELECT top(10) ID
    FROM test  
    WHERE  Created >= '2018-08-02 22:49:01'
    AND Type IN (1, 4)
    ORDER BY ID -- clustered index scan

SELECT top(10) ID
    FROM test  
    WHERE  Created >= '2018-08-02 22:49:01.577'
    AND Type IN (1, 4)
    ORDER BY ID-- index seek of ncl1
3
jesijesi

一般的で最も基本的な用語として、Index scanのコストがIndex Seek未満の場合、オプティマイザーはIndex Scanを決定する場合があります。

SELECT top(10) ID
    FROM test  
    WHERE  Created >= '2018-08-02 22:49:01'
    AND Type IN (1, 4)
    ORDER BY ID -- clustered index scan

この場合、'2018-08-02 22:49:01'より大きいレコードが多数あり、10レコードのみが必要です。

したがって、オプティマイザーがインデックスからレコードを取得する場合、コストはさらに高くなります。

それでIndex Scanとこの「十分な計画が見つかりました」

SELECT top(10) ID
    FROM test  
    WHERE  Created >= '2018-08-02 22:49:01.577'
    AND Type IN (1, 4)
    ORDER BY ID-- index seek of ncl1

ここでは'2018-08-02 22:49:01.577'よりも大きいレコードが非常に少ないため、これらの10個のレコードから、オプティマイザーがIndex Seekに移動することを望んでいます。

ここで、Index Seek演算子が'2018-08-02 22:49:01.577'より大きいすべての行を返すことに気づくでしょう。実際の行数は、'2018-08-02 22:49:01.577'より大きいすべての行です。次に、Sortオペレーターはそれを10にスライスします。

したがって、「十分な計画が見つかりました」ではない可能性があります。

0
KumarHarsh