Ho una domanda in cui l'utilizzo select *
non solo fa molto meno letture, ma utilizza anche significativamente meno tempo della CPU rispetto all'utilizzo select c.Foo
.
Questa è la domanda:
select top 1000 c.ID
from ATable a
join BTable b on b.OrderKey = a.OrderKey and b.ClientId = a.ClientId
join CTable c on c.OrderId = b.OrderId and c.ShipKey = a.ShipKey
where (a.NextAnalysisDate is null or a.NextAnalysisDate < @dateCutOff)
and b.IsVoided = 0
and c.ComplianceStatus in (3, 5)
and c.ShipmentStatus in (1, 5, 6)
order by a.LastAnalyzedDate
Ciò terminò con 2.473.658 letture logiche, principalmente nella Tabella B. Utilizzava 26.562 CPU e aveva una durata di 7.965.
Questo è il piano di query generato:
Su PasteThePlan: https://www.brentozar.com/pastetheplan/?id=BJAp2mQIQ
Quando cambio c.ID
a *
, la query è terminata con 107.049 letture logiche, distribuite in modo abbastanza uniforme tra tutte e tre le tabelle. Utilizzava 4.266 CPU e aveva una durata di 1.147.
Questo è il piano di query generato:
Su PasteThePlan: https://www.brentozar.com/pastetheplan/?id=SyZYn7QUQ
Ho provato a utilizzare i suggerimenti per le query suggeriti da Joe Obbish, con questi risultati:
select c.ID
senza suggerimento: https://www.brentozar.com/pastetheplan/?id=SJfBdOELm
select c.ID
con suggerimento: https://www.brentozar.com/pastetheplan/ ? id = B1W ___ N87
select *
senza suggerimento: https://www.brentozar.com/pastetheplan/?id=HJ6qddEIm
select *
con suggerimento: https://www.brentozar.com/pastetheplan/?id=rJhhudNIQ
L'uso del OPTION(LOOP JOIN)
suggerimento con select c.ID
ha ridotto drasticamente il numero di letture rispetto alla versione senza suggerimento, ma sta ancora facendo circa il doppio del numero di letture della select *
query senza alcun suggerimento. L'aggiunta OPTION(RECOMPILE, HASH JOIN)
alla select *
query ha reso le prestazioni molto peggiori di qualsiasi altra cosa che abbia provato.
Dopo aver aggiornato le statistiche sulle tabelle e sui loro indici utilizzando WITH FULLSCAN
, la select c.ID
query viene eseguita molto più velocemente:
select c.ID
prima dell'aggiornamento: https://www.brentozar.com/pastetheplan/?id=SkiYoOEUm
select *
prima dell'aggiornamento: https://www.brentozar.com/ pastetheplan /? id = ryrvodEUX
select c.ID
dopo l'aggiornamento: https://www.brentozar.com/pastetheplan/?id=B1MRoO487
select *
dopo l'aggiornamento: https://www.brentozar.com/pastetheplan/?id=Hk7si_V8m
select *
supera ancora select c.ID
in termini di durata totale e letture totali ( select *
ha circa la metà delle letture) ma utilizza più CPU. Nel complesso sono molto più vicini rispetto a prima dell'aggiornamento, tuttavia i piani sono ancora diversi.
Lo stesso comportamento si riscontra nel 2016 in esecuzione nella modalità di compatibilità 2014 e nel 2014. Cosa potrebbe spiegare la disparità tra i due piani? Potrebbe essere che gli indici "corretti" non siano stati creati? Le statistiche che potrebbero essere leggermente obsolete potrebbero causare questo?
Ho provato a spostare i predicati fino alla ON
parte del join, in diversi modi, ma il piano di query è lo stesso ogni volta.
Dopo la ricostruzione dell'indice
Ho ricostruito tutti gli indici sulle tre tabelle coinvolte nella query. c.ID
sta ancora eseguendo il maggior numero di letture (oltre il doppio *
), ma l'utilizzo della CPU è circa la metà della *
versione. La c.ID
versione anche riversata in tempdb sul smistamento di ATable
:
c.ID
: https://www.brentozar.com/pastetheplan/?id=HyHIeDO87
*
: https://www.brentozar.com/pastetheplan/?id=rJ4deDOIQ
Ho anche provato a forzarlo a funzionare senza parallelismo e questo mi ha dato la query con le migliori prestazioni: https://www.brentozar.com/pastetheplan/?id=SJn9-vuLX
Vedo il numero di esecuzioni degli operatori DOPO la ricerca del grande indice che sta eseguendo l'ordinamento eseguito solo 1.000 volte nella versione a thread singolo, ma ha fatto significativamente di più nella versione parallela, tra 2.622 e 4.315 esecuzioni di vari operatori.
select c.ID
query molto più veloce, ma sta ancora facendo un lavoro extra che laselect *
query, senza suggerimenti, fa.