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
一般的で最も基本的な用語として、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にスライスします。
したがって、「十分な計画が見つかりました」ではない可能性があります。