मेरे पास एक क्वेरी है जहां उपयोग करना select *
न केवल बहुत कम पढ़ता है, बल्कि उपयोग करने की तुलना में काफी कम सीपीयू समय का उपयोग करता है select c.Foo
।
यह प्रश्न है:
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
यह 2,473,658 तार्किक रीड के साथ समाप्त हुआ, ज्यादातर टेबल बी में। इसमें 26,562 सीपीयू का इस्तेमाल किया गया और इसकी अवधि 7,965 थी।
यह उत्पन्न क्वेरी योजना है:
PasteThePlan पर: https://www.brentozar.com/pastetheplan/?id=BJAp2PQQQ
जब मैं बदलने c.ID
के लिए *
, क्वेरी के साथ समाप्त 107,049 तार्किक पढ़ता है, काफी समान रूप से सभी तीन तालिकाओं के बीच फैल गया। इसमें 4,266 सीपीयू का इस्तेमाल किया गया था और इसकी अवधि 1,147 थी।
यह उत्पन्न क्वेरी योजना है:
PasteThePlan पर: https://www.brentozar.com/pastetheplan/?id=SyZYn7QUQ
मैंने जो ओबिश द्वारा सुझाए गए क्वेरी संकेत का उपयोग करने का प्रयास किया, इन परिणामों के साथ:
select c.ID
बिना संकेत: https://www.brentozar.com/pastetheplan/?id=SJfBdOELm
select c.ID
with hint: https://www.brentozar.com/pastetheplan/ ? आईडी = B1W ___ N87
select *
बिना संकेत के: https://www.brentozar.com/pastetheplan/?id=HJ6qddEIm
select *
with hint: https://www.brentozar.com/pastetheplan-?id=rJhudNIQ
OPTION(LOOP JOIN)
संकेत का उपयोग करते हुए संकेत के select c.ID
बिना संस्करण की तुलना में रीड्स की संख्या को काफी कम कर दिया है, लेकिन यह अभी भी लगभग 4x कर रहा है select *
बिना किसी संकेत के क्वेरी को पढ़ता है। क्वेरी में जोड़ने OPTION(RECOMPILE, HASH JOIN)
से select *
यह मेरे द्वारा किए गए किसी भी प्रयास की तुलना में बहुत खराब प्रदर्शन करता है।
तालिकाओं और उनके अनुक्रमित का उपयोग करने के आंकड़ों को अपडेट करने के बाद WITH FULLSCAN
, select c.ID
क्वेरी बहुत तेजी से चल रही है:
select c.ID
अपडेट से पहले: https://www.brentozar.com/pastetheplan/?id=SkiYoOEUm
select *
अपडेट से पहले: https://www.brentozar.com/ pastetheplan /? id = ryrvodEUX
select c.ID
अपडेट के बाद: https://www.brentozar.com/pastetheplan/?id=B1MRoO487
select *
अपडेट के बाद: https://www.brentozar.com/pastetheplan/?id=Hk7si_V8m
select *
अभी भी select c.ID
कुल अवधि और कुल पढ़ता है ( select *
लगभग आधा पढ़ता है) के संदर्भ में, लेकिन यह अधिक सीपीयू का उपयोग करता है। कुल मिलाकर वे अद्यतन से पहले की तुलना में बहुत करीब हैं, हालांकि योजनाएं अभी भी अलग हैं।
2016 में 2014 की संगतता मोड और 2014 में एक ही व्यवहार देखा गया है। दोनों योजनाओं के बीच असमानता को क्या समझा सकता है? क्या ऐसा हो सकता है कि "सही" इंडेक्स नहीं बनाए गए हैं? क्या आंकड़े थोड़ा आउट ऑफ डेट हो सकते हैं?
मैंने ON
कई तरीकों से, शामिल होने के भाग तक विधेय को स्थानांतरित करने का प्रयास किया , लेकिन प्रत्येक बार क्वेरी योजना समान है।
इंडेक्स रीबिल्ड्स के बाद
मैंने क्वेरी में शामिल तीन तालिकाओं पर सभी अनुक्रमित को फिर से बनाया है। c.ID
अभी भी सबसे अधिक पढ़ता है (दो बार से अधिक के रूप में *
), लेकिन CPU उपयोग *
संस्करण का लगभग आधा है । c.ID
संस्करण भी की छंटाई पर tempdb में गिरा ATable
:
c.ID
: https://www.brentozar.com/pastetheplan/?id=HyHIeDO87
*
: https://www.brentozar.com/pastetheplan/?id=rJ4deDOIQ
मैंने इसे बिना समानता के संचालित करने के लिए मजबूर करने की कोशिश की, और इससे मुझे सबसे अच्छा प्रदर्शन करने वाला प्रश्न मिला: https://www.brentozar.com/pastetheplan/?id=SJn9-vuLX
मैं संचालकों की निष्पादन गणना पर ध्यान देता हूं कि बड़े सूचकांक की तलाश है जो केवल एकल-थ्रेडेड संस्करण में 1,000 बार निष्पादित की गई ऑर्डर कर रहा है, लेकिन विभिन्न ऑपरेटरों के 2,622 और 4,315 निष्पादन के बीच, समानांतर संस्करण में काफी अधिक है।
select c.ID
क्वेरी को बहुत तेज़ कर दिया, लेकिन यह अभी भी कुछ अतिरिक्त काम कर रहा हैselect *
, जो क्वेरी, बिना संकेत के करता है।