2010-05-07 91 views
2

繼上我的最後一個問題Sql Server query performance,並發現我的方法在一個搜索查詢中允許可選參數是次優的,是否有人有如何解決這個問題的指導方針?最佳搜索查詢

例如,假設我有一個應用程序表,一個客戶表和一個聯繫人詳細信息表,並且我想創建一個SP,該SP允許在某些姓名,家庭電話,手機和應用程序ID,可以使用類似以下內容:

select * 
from application a inner join customer c on a.customerid = a.id 
    left join contact hp on (c.id = hp.customerid and hp.contacttype = 'homephone') 
    left join contact mob on (c.id = mob.customerid and mob.contacttype = 'mobile') 
where (a.ID = @ID or @ID is null) 
    and (c.Surname = @Surname or @Surname is null) 
    and (HP.phonenumber = @Homphone or @Homephone is null) 
    and (MOB.phonenumber = @Mobile or @Mobile is null) 

上面使用的模式是不是真實的,我也不會使用select *在真實的場景中,它是在where子句我感興趣的建設。有沒有更好的方法,無論是動態sql還是可以實現相同結果的替代方法,而不需要很多嵌套條件。一些SP可具有10 - 以這種方式使用

回答

3

沒有「一刀切」這種查詢方法,也有多麼細微的性能影響你做這個。如果您想超越只是讓查詢返回正確的答案,不管它有多慢,看看這篇文章:Dynamic Search Conditions in T-SQL by Erland Sommarskog。它涵蓋了每種方法,並且非常詳細地給出了每種方法的PRO和Cons。

如果您可以確定搜索列的最小和最大可能範圍,並且搜索列不是NULL,那麼您可以比(@Search IS NULL或Col = @ Search),see this area of the above linked article做得更好。不過,你應該閱讀整篇文章,有很多變化取決於你的情況,你真的需要學習多種方法以及何時使用它們。

也看到這個其他最近的答案:SQL Server 2008 - Conditional Query

+1

+1:很好的參考文章! – RedFilter 2010-05-07 12:41:49

+0

偉大的文章,我被幾個DBA告知,動態SQL是邪惡的(即使使用sp_executesql),但實際上並沒有研究自己。重寫一些關鍵的查詢來使用這種方法已經有了重大的改進 – Macros 2010-05-09 12:54:59

1

好15標準,在這裏我們去

OPTION(RECOMPILE)

是必須的 - 否則第一個查詢計劃被重用,無論怎樣的參數比賽。對不起,沒有辦法做得更好。

除此之外 - 不,對不起。動態SQL可以獲得更高的效率(通過避免IS NULL替代方法),但是如果不可能,你基本上已經確定了它。

使用動態SQL你基本不用爲艾琳如果HP.phonenumber的HOMEPHONE變量爲null;)

1

在你的情況下,不同的查詢將使用不同的指標。

你應該定義一組要使用和編寫每一套單獨的查詢索引,以UNION ALL對索引字段替換OR

SELECT * 
FROM tables 
WHERE A = @ID 
     AND (c.Surname = @Surname or @Surname IS NULL) 
     AND (HP.phonenumber = @Homphone or @Homephone IS NULL) 
     AND (MOB.phonenumber = @Mobile or @Mobile IS NULL) 
UNION ALL 
SELECT * 
FROM tables 
WHERE @ID IS NULL 
     AND c.Surname = @Surname 
     AND (HP.phonenumber = @Homphone or @Homephone IS NULL) 
     AND (MOB.phonenumber = @Mobile or @Mobile IS NULL) 
UNION ALL 
SELECT * 
FROM tables 
WHERE @ID IS NULL 
     AND @Surname IS NULL 
     AND (HP.phonenumber = @Homphone or @Homephone IS NULL) 
     AND (MOB.phonenumber = @Mobile or @Mobile IS NULL)