Domanda

Ho bisogno di trovare così chiamata prima voce nel database per gli elementi per quanto riguarda i loro partner. Ho scritto query e mi sta dando risultati corretti ma succhia con prestazioni.
Ho il sospetto che ho perso la concezione quindi questa query può essere scritta molto meglio. Quindi vi chiedo di aiutarmi a ridisegno questa query per ottenere prestazioni migliori.
Il mio sistema di database in esecuzione è 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
È stato utile?

Soluzione

La prima questo che vorrei provare è quello di aggiungere dove doc.datum> = @ od_datuma e doc.datum <= @ do_datuma perché la clausola having. Forse sarà dare un suggerimento al pianificatore query. Poi la grande domanda è: perché l'outer join con il subquery? Conviene la "dove .. stari_uazi.ART_ID è nullo" significa che si desidera escludere tutte le righe di ritorno dalla subquery? Ho il sospetto che la subquery è il vero assassino perché la ricerca della DOC non è limitato (DOC.DATUM <@od_datuma), quindi potrebbe prendere un enorme numero di righe, che non hanno scopo reale in quanto esclude di query genitore queste righe comunque ..

La mia ipotesi è che se si elimina la subquery (join esterno sinistro ..) si avrà qualcosa di molto vicino a ciò che si vuole, molto più veloce. Se avete bisogno di sopprimere alcune righe dal set di risultati si possono mettere in una tabella temporanea ed eliminarli in seguito, questo potrebbe essere più veloce rispetto al outer join subquery.

Aggiornamento: quindi se si desidera mantenere solo le righe tra @od / @Do _datum, rimuovere il join sinistro e aggiungere la condizione where DOC.DATUM between @od_ and @do_ Avrete lo stesso risultato e sarà molto più veloce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top