SQL Server 中Inner join 和where的效率差異
今天,手頭上正在作的一個(gè)項(xiàng)目,在生成報(bào)表時(shí),客戶感覺(jué)太慢,于是,各處檢查,看可否提示效率。界面上的都改進(jìn)了,提升不大。如是在SQL 語(yǔ)句上下功夫。(我這人比較懶,對(duì)簡(jiǎn)單的語(yǔ)句和查詢都沒(méi)有經(jīng)過(guò)仔細(xì)優(yōu)化的,一般只對(duì)姚使用left join,outer join,group by 以及carsor的語(yǔ)句會(huì)仔細(xì)寫(xiě)并用數(shù)據(jù)庫(kù)理論考慮和檢查---因?yàn)檫@種語(yǔ)句一般測(cè)試時(shí)如果發(fā)現(xiàn)錯(cuò)誤,檢查和調(diào)試很麻煩)
先在網(wǎng)上Google搜索“Join 與 Where 效率”以及察看SQL Server 幫助文檔,希望能獲得“捷徑”些的優(yōu)化思路。
搜索的結(jié)果是,各大論壇,包括MSDN上很多人提出了這個(gè)問(wèn)題,但回答是眾說(shuō)紛紜。總體上總結(jié)出來(lái)時(shí)說(shuō):對(duì)小數(shù)據(jù)量(<N萬(wàn))的來(lái)說(shuō)效率幾乎無(wú)差異,更有說(shuō)法說(shuō)Inner join 和Where只是SQL標(biāo)準(zhǔn)不同,在查詢分析器中SQL Server查詢分析器是將Where直接轉(zhuǎn)換為Join后查詢的。
還是自己來(lái)做試驗(yàn)吧。
如是有了如下比較結(jié)果(均在查詢分析器中查詢和計(jì)時(shí)):
語(yǔ)句(1)declare @operatorName nvarchar(50)set @operatorName = '%'
select distinct item.*; from item , customer_item , customer_operator ,operatorwhere item.itemcode = customer_item.itemCode and customer_item.customerCode =; customer_operator.customerCodeand customer_operator.operatorId =; customer_operator.operatorIdand operator.operatorName like @operatorNameand item.deleted = 0 and customer_item.deleted = 0 and customer_operator.deleted = 0查詢結(jié)果,74行,共時(shí)間0:00:04
語(yǔ)句(2)declare @operatorName nvarchar(50)
set @operatorName = '%'
select distinct item.*; from item inner join; customer_item on; item.itemcode = customer_item.itemCode inner join customer_operator on customer_item.customerCode = customer_operator.customerCodeinner join operator on customer_operator.operatorId = operator.operatorIdwhere; operator.operatorName like @operatorNameand item.deleted = 0 and customer_item.deleted = 0 and customer_operator.deleted = 0共74行,時(shí)間0:00:01
后檢查發(fā)現(xiàn)語(yǔ)句(1)中有一個(gè)重復(fù)自查詢條件 :customer_operator.operatorId =; customer_operator.operatorId將其葉加到語(yǔ)句2中,語(yǔ)句(3)declare @operatorName nvarchar(50)
set @operatorName = '%'
select distinct item.*; from item inner join; customer_item on; item.itemcode = customer_item.itemCode inner join customer_operator on customer_item.customerCode = customer_operator.customerCodeinner join operator on customer_operator.operatorId = operator.operatorIdwhere; operator.operatorName like @operatorNameand item.deleted = 0 and customer_item.deleted = 0 and customer_operator.deleted = 0and customer_operator.operatorId =; customer_operator.operatorId
所用時(shí)間和結(jié)果都為74行,時(shí)間0:00:01。
將語(yǔ)句(1)中的去掉該條件后成為語(yǔ)句(4)declare @operatorName nvarchar(50)set @operatorName = '%'
select distinct item.*; from item , customer_item , customer_operator ,operatorwhere item.itemcode = customer_item.itemCode and customer_item.customerCode =; customer_operator.customerCode--and customer_operator.operatorId =; customer_operator.operatorIdand operator.operatorName like @operatorNameand item.deleted = 0 and customer_item.deleted = 0 and customer_operator.deleted = 0
時(shí)間和結(jié)果為74行,時(shí)間0:00:01。
終于發(fā)現(xiàn)了些他們的差異。
結(jié)論: 盡量使用Join 而不是Where來(lái)列出關(guān)聯(lián)條件,特別是多個(gè)表聯(lián)合的時(shí)候。原因是: (1)在效率上,Where可能具有和Inner join一樣的效率。但基本可以肯定的(通過(guò)SQLServer幫助和其它資料,以及本測(cè)試)是Join的效率不比Where差。 (2)使用Join可以幫助檢查語(yǔ)句中的無(wú)效或者誤寫(xiě)的關(guān)聯(lián)條件

網(wǎng)公網(wǎng)安備