以下の例では、Index Spool
の結果はすでにソートされていますが、単純なTop
ではなくTop N Sort
がここにあるのはなぜですか?
use tempdb;
go
create table dbo.t1 (id int identity primary key, v int);
create table dbo.t2 (id int identity primary key, v int);
insert into dbo.t1
(v)
select top (1000)
row_number() over (order by 1/0)
from
master.dbo.spt_values a cross join
master.dbo.spt_values b;
insert into dbo.t2
(v)
select top (10000)
row_number() over (order by 1/0) + 10000
from
master.dbo.spt_values a cross join
master.dbo.spt_values b;
set statistics xml, io on;
select
sum(a.v + b.v)
from
dbo.t1 a outer apply
(select top (1) v from dbo.t2 where v >= a.v order by v) b;
set statistics xml,io off;
go
drop table dbo.t1, dbo.t2;
go
2008 R2
以降のすべてのバージョンで再現可能です(テストする以前のバージョンのサーバーはありません)
これは、現在のオプティマイザのやや厄介な制限です。
The Eager Index Spool and The Optimizer の一部としてこれについて少し書きました:
インデックススプールは、スプールのインデックスキーによって順序付けられた出力をサポートすることをオプティマイザに伝えません。スプールからのソートされた出力が必要な場合、不要なソート演算子が表示されることがあります。とにかく、インデックススプールは多くの場合、永続インデックスに置き換える必要があるため、ほとんどの場合、これは軽微な問題です。