Mi aiutano a progettare meglio la mia domanda in modo da poter ottenere più prestazioni
-
16-10-2019 - |
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
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.