select *
Sadece çok daha az okuma kullanarak değil, aynı zamanda kullanmaktan çok daha az CPU zamanı kullanan bir sorgu var select c.Foo
.
Bu sorgu:
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
Bu, çoğunlukla Tablo B'de 2,473,658 mantıksal okuma ile sona erdi. 26,562 CPU kullandı ve 7,965 sürdü.
Oluşturulan sorgu planı şudur:
PasteThePlan'da: https://www.brentozar.com/pastetheplan/?id=BJAp2mQIQ
Ben değiştirdiğinizde c.ID
için *
, sorgu mantıksal 107.049 oldukça eşit üç tablo arasında yayılmış, okur ile tamamladı. 4.266 CPU kullandı ve 1.147 süresine sahipti.
Oluşturulan sorgu planı şudur:
PasteThePlan'da: https://www.brentozar.com/pastetheplan/?id=SyZYn7QUQ
Joe Obbish tarafından önerilen sorgu ipuçlarını şu sonuçlarla kullanmaya çalıştım:
select c.ID
ipucu olmadan: https://www.brentozar.com/pastetheplan/?id=SJfBdOELm
select c.ID
ipucu ile: https://www.brentozar.com/pastetheplan/ ? id = B1W ___
select *
İpucu olmadan ipucu: https://www.brentozar.com/pastetheplan/?id=HJ6qddEIm
select *
ile ipucu: https://www.brentozar.com/pastetheplan/?id=rJhhudNIQ
İpucunun kullanılması, OPTION(LOOP JOIN)
ipucu select c.ID
olmadan sürüme kıyasla okuma sayısını önemli ölçüde azalttı, ancak yine de select *
herhangi bir ipucu olmadan sorgu okuma sayısını yaklaşık 4 kat yapıyor . Sorgu eklemek OPTION(RECOMPILE, HASH JOIN)
, select *
ben denedim başka bir şey çok daha kötü performans yaptı.
Tablolar ve kullanarak endeksler ilgili istatistikleri güncelledikten sonra WITH FULLSCAN
, select c.ID
sorgu çalışırken çok daha hızlı:
select c.ID
güncellemeden önce: https://www.brentozar.com/pastetheplan/?id=SkiYoOEUm
select *
güncellemeden önce: https://www.brentozar.com/
select c.ID
Güncellemeden sonra pastetheplan /? id = ryrvodEUX : https://www.brentozar.com/pastetheplan/?id=B1MRoO487
select *
güncelleme sonrası: https://www.brentozar.com/pastetheplan/?id=Hk7si_V8m
select *
select c.ID
toplam süre ve toplam okuma sayısı bakımından hala daha iyi performans gösteriyor (okumaların select *
yaklaşık yarısı var) ancak daha fazla CPU kullanıyor. Genel olarak, güncellemeden çok daha yakınlar, ancak planlar hala farklı.
Aynı davranış, 2014 Uyumluluk modunda çalışan 2014 ve 2014'te de görülür. İki plan arasındaki eşitsizliği ne açıklayabilir? "Doğru" indeksler oluşturulmamış olabilir mi? İstatistikler biraz güncelliğini yitirmiş olabilir mi?
Tahminleri ON
birleştirme kısmına kadar birden çok şekilde taşımaya çalıştım , ancak sorgu planı her seferinde aynı.
Endeks Yeniden Oluşturulduktan Sonra
Sorguda yer alan üç tablodaki tüm dizinleri yeniden oluşturdum. c.ID
hala en çok okunan değeri (iki katından fazla *
) yapıyor, ancak CPU kullanımı *
sürümün yaklaşık yarısı . c.ID
Sürümü de malzemelerin tasnifi üzerinde tempdb içine dökülen ATable
:
c.ID
: https://www.brentozar.com/pastetheplan/?id=HyHIeDO87
*
: https://www.brentozar.com/pastetheplan/?id=rJ4deDOIQ
Ayrıca paralellik olmadan çalışmaya zorlamaya çalıştım ve bu bana en iyi performans gösteren sorguyu verdi: https://www.brentozar.com/pastetheplan/?id=SJn9-vuLX
Tek iş parçacıklı sürümde yalnızca 1.000 kez yürütülen, ancak çeşitli işleçlerin 2.622 ve 4.315 yürütme arasında Paralelleştirilmiş sürümde yapılan büyük dizin aramasından SONRA operatörlerin yürütme sayısını fark ettim.
select c.ID
Sorguyu çok daha hızlı hale getirdi, ancak halaselect *
ipucu olmadan sorgunun yaptığı bazı ekstra işler yapıyor.