web-dev-qa-db-ja.com

この例でなぜトップNソートがあるのですか?

以下の例では、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

enter image description here

2008 R2以降のすべてのバージョンで再現可能です(テストする以前のバージョンのサーバーはありません)

6
sepupic

これは、現在のオプティマイザのやや厄介な制限です。

The Eager Index Spool and The Optimizer の一部としてこれについて少し書きました:

インデックススプールは、スプールのインデックスキーによって順序付けられた出力をサポートすることをオプティマイザに伝えません。スプールからのソートされた出力が必要な場合、不要なソート演算子が表示されることがあります。とにかく、インデックススプールは多くの場合、永続インデックスに置き換える必要があるため、ほとんどの場合、これは軽微な問題です。

2
Paul White 9