SQL Server 2005を使用していて、IN句内でサブクエリを使用しているときにいくつかの結果をフィルタリングするときに奇妙なことに気付きました。例えば、これは私の現在のクエリであり、それは平均で70秒で実行されます:私は2つの別々のクエリにそれらを打破する場合IN(サブクエリ)を使用するとパフォーマンスが大幅に低下します。どうして?
select Phone, ZipCode, sum(Calls) as Calls, sum(Sales) as Sales
from Archive
where CustomerID = 20
and ReportDate = '2/3/2011'
and Phone in (
select Phone
from PlanDetails
where Phone is not null
and Length is not null
and PlannedImp > 0
and CustomerID = 20
and (StatusID <> 2 and StatusID <> 7)
and SubcategoryID = 88
)
group by Phone, ZipCode
はしかし、彼らが実行するために1秒ごとの下で取ります。
select Phone
from PlanDetails
where Phone is not null
and Length is not null
and PlannedImp > 0
and CustomerID = 20
and (StatusID <> 2 and StatusID <> 7)
and SubcategoryID = 88
と最後に
select Phone, ZipCode, sum(Calls) as Calls, sum(Sales) as Sales
from Archive
where CustomerID = 20
and ReportDate = '2/3/2011'
group by Phone, ZipCode
、私はこれが最初のクエリと同じ結果を返しますが、およそ2〜3秒で行う場合:過去数について
select Phone
into #tempTable
from PlanDetails
where Phone is not null
and Length is not null
and PlannedImp > 0
and CustomerID = 20
and (StatusID <> 2 and StatusID <> 7)
and SubcategoryID = 88
select Phone, ZipCode, sum(Calls) as Calls, sum(Sales) as Sales
from Archive
where CustomerID = 20
and ReportDate = '2/3/2011'
and Phone in (
select Phone
from #tempTable
)
group by Phone, ZipCode
私はこのクエリが遅いのではなく、IN句の中で(やや複雑な)サブクエリを使用するクエリがパフォーマンスを壊すだけであることに気づいています。その理由は何ですか?
これらのクエリで使用できるインデックスは、両方のテーブルのCustomerIDの非クラスタ化インデックスのみです。私は、低速クエリと高速クエリの両方の実行計画を見て、非クラスタ化インデックスがArchiveテーブルを検索することは、コストの最も高いパーセンテージ(80〜90%)を占めることを確認しました。しかし、唯一の違いは、低速クエリのステップではCPUコストが7.1で、高速クエリではCPUコストが1.7であることです。
この種の不具合(間違ったクエリプラン)が発生すると、sp_updatestatsを実行すると問題が解決することがあります。 – Magnus