Sql-Server

幫助我更好地設計查詢,以便獲得更高的性能

  • January 29, 2012

我需要在數據庫中找到所謂的第一個條目,以獲取有關其合作夥伴的項目。我寫了查詢,它給了我正確的結果,但性能很糟糕。

我懷疑我錯過了概念,因此這個查詢可以寫得更好。所以我請你幫我重新設計這個查詢以獲得更好的性能。

我執行的數據庫系統是 Sql Server 2008

declare @od_datuma datetime
declare @do_datuma datetime

set @od_datuma='2011-12-01'
set @do_datuma='2011-12-31'


select 
doc.PAR_ID
,sdo.art_id
,MIN(doc.id) as doc_id
from 
dokumenti
inner join DOC on dokumenti.tip=DOC.TIP
inner join SDO on DOC.ID=SDO.DOC_ID
left  outer join (
   select par_id,art_id from dokumenti
           inner join DOC on dokumenti.tip=DOC.TIP
           inner join SDO on DOC.ID=SDO.DOC_ID     
           where   dokumenti.NABAVA =1 and
                   dokumenti.KOL_UL=1 and
                   DOC.DATUM<@od_datuma
               )  as stari_uazi on DOC.PAR_ID=stari_uazi.PAR_ID and SDO.ART_ID=stari_uazi.ART_ID
where 
dokumenti.NABAVA =1 and
dokumenti.KOL_UL=1 and
stari_uazi.ART_ID is null and 
doc.datum between @od_datuma and @do_datuma
group by doc.PAR_ID,sdo.art_id

我要嘗試的第一個是添加 where doc.datum>=@od_datuma 和 doc.datum <=@do_datuma 因為有子句。也許它會給查詢計劃者一個提示。那麼最大的問題是:為什麼外連接與子查詢?“ where .. stari_uazi.ART_ID is null ”是否意味著您要排除從子查詢返回的所有行?我懷疑子查詢是真正的殺手,因為對 DOC 的搜尋是無界的( DOC.DATUM <@od_datuma ),所以它可能會獲取大量的行,這些行沒有真正的目的,因為父查詢無論如何都排除了這些行。

我的猜測是,如果您抑制子查詢(左外連接..),您將獲得與您想要的非常接近的東西,而且速度要快得多。如果您需要抑制結果集中的某些行,您可以將它們放在臨時表中並在之後刪除它們,這可能比外部連接子查詢更快。

更新:因此,如果您只想保留 @od / @do _datum 之間的行,請刪除左連接並添加條件where DOC.DATUM between @od_ and @do_ 您將獲得相同的結果,並且速度會快得多。

引用自:https://dba.stackexchange.com/questions/11843