2012-10-05 30 views
0

一個如何優化這個查詢:優化where子句(短路)時,SQL Server 2008

declare @MyParam nvarchar(100) = 25846987; 

select top 100 * from MySelectTable 
where 
(MyParam = @MyParam) 
OR 
(@MyParam = 0 and MyParam in (SELECT MyParam FROM aMassiveSlowTable WHERE Id = 'random1')) 
OR 
(@MyParam = 1 and MyParam in (SELECT MyParam FROM aMassiveSlowTable WHERE Id = 'random2')) 
OR 
(@MyParam = 2 and MyParam in (SELECT MyParam FROM aMassiveSlowTable WHERE Id = 'random3')) 

當我只用這部分:

declare @MyParam nvarchar(100) = 25846987; 

select top 100 * from MySelectTable 
where 
(MyParam = @MyParam) 

它返回1秒。

使用所有參數時,大約需要5分鐘。

我相信這是因爲它只是在匹配MyParam = @MyParam時掃描一個MassiveSlowTable。

如果@MyParam匹配MyParam,我該如何跳過所有其他比較?我嘗試使用CASE語句,但它們不適用於IN子句。我嘗試重新排列並列中的AND,甚至在aMassiveSlowTable中添加額外的過濾。

如果@MyParam與MyParam不匹配,則查詢花費一點時間就可以。

+3

有表現不佳:可以查看以下KB:

FIX *否*保證SQL Server將評估單個查詢的部分的順序(例如,它可能會計算SELECT'子句的一個計算結果,該計算結果可能會被'WHERE'子句排除)。 –

+0

@Damien我開始這麼想。 –

+0

你可以發表兩個表的定義,指數和執行計劃嗎? –

回答

0

這可能會解決它
在它應該得到評估早期

(MyParam in (SELECT MyParam FROM aMassiveSlowTable WHERE Id = 'random1' and @MyParam = 0)) 

declare @MyParam nvarchar(100) = 25846987; 
select * 
from MySelectTable 
where MyParam = @MyParam 
union 
select * 
from MySelectTable 
join aMassiveSlowTable as Slow 
and Slow.MyParam = MySelectTable.MyParam 
and Slow.ID = 'random0' 
where @MyParam = 0 
union 
select * 
from MySelectTable 
join aMassiveSlowTable as Slow 
and Slow.MyParam = MySelectTable.MyParam 
and Slow.ID = 'random1' 
where @MyParam = 1 
union 
select * 
from MySelectTable 
join aMassiveSlowTable as Slow 
and Slow.MyParam = MySelectTable.MyParam 
and Slow.ID = 'random2' 
where @MyParam = 2 

或與該聯接提示

declare @MyParam nvarchar(100) = 25846987; 
select top 100 * 
from MySelectTable 
left join aMassiveSlowTable as Slow 
    on Slow.MyParam in (1,2,3) -- now the optimizer has something hard to evalate 
and Slow.MyParam = MySelectTable.MyParam 
or (Slow.MyParam = 0 and Slow.ID = 'random0') 
or (Slow.MyParam = 1 and Slow.ID = 'random1') 
or (Slow.MyParam = 2 and Slow.ID = 'random2') 
where MyParam = @MyParam 
+0

我嘗試了第一部分,但它並沒有幫助(這就是我說的_adding其他過濾到aMassiveSlowTable_的意思,我會嘗試其他方法。 –