sp_cursorprepexec 53 मिलियन रीड का कारण बनता है?


9

हम SQL Server 2012 के साथ एक Dynamics AX 2012 स्थापना चला रहे हैं। मुझे पता है कि कर्सर का अब उपयोग नहीं किया जाना चाहिए, लेकिन AX इसका उपयोग कर रहा है और हम इस व्यवहार को बदल नहीं सकते हैं इसलिए हमें इसके साथ काम करना होगा।

आज मैंने 53 मिलियन से अधिक रीड्स और 20 मिनट से अधिक के निष्पादन समय के साथ बहुत खराब क्वेरी पकड़ी।

मैंने हमारे निगरानी उपकरण SentryOne के माध्यम से इस क्वेरी को पकड़ा।

declare @p1 int
set @p1=1073773227
declare @p2 int
set @p2=180158805
declare @p5 int
set @p5=16
declare @p6 int
set @p6=1
declare @p7 int
set @p7=2
exec sp_cursorprepexec @p1 output,@p2 output,N'@P1 bigint,@P2 nvarchar(5),@P3 bigint,@P4 nvarchar(8),@P5 bigint,@P6 bigint,@P7 bigint,@P8 bigint,@P9 bigint,@P10 bigint,@P11 bigint,@P12 bigint,@P13 bigint,@P14 bigint,@P15 bigint,@P16 bigint,@P17 bigint,@P18 bigint,@P19 nvarchar(5),@P20 bigint,@P21 bigint,@P22 bigint,@P23 bigint,@P24 bigint',N'SELECT T1.PRODUCT,T1.EXTERNALVENDPARTY,T1.LIFECYCLESTATUS,T1.RECID,T2.ECORESPRODUCT,T2.ECORESDISTINCTPRODUCTVARIANT,T2.SGE,T2.ECORESREFORDERNUM,T2.ORDERNUM,T2.RECID,T3.ECORESREFORDERNUM,T3.NAME1,T3.NAME2,T3.NAME3,T3.RECID,T4.ECORESPRODUCT,T4.EXTERNALITEMID,T4.ECORESDISTINCTPRODUCTVARIANT,T4.RECID,T5.RECID,T5.PERSON,T6.RECID,T6.NAME,T6.INSTANCERELATIONTYPE,T7.RECID,T7.NAME,T7.INSTANCERELATIONTYPE,T8.PARTY,T8.ACCOUNTNUM,T8.RECID,T9.RECID,T9.DISPLAYPRODUCTNUMBER,T9.INSTANCERELATIONTYPE,T10.PRODUCT,T10.CATEGORY,T10.RECID,T11.RECID,T11.CODE,T11.NAME,T11.INSTANCERELATIONTYPE FROM INVENTTABLE T1 CROSS JOIN ECORESPRODUCTORDERNUM T2 CROSS JOIN ECORESPRODUCTORDERNUMTRANSLATION T3 LEFT OUTER JOIN VENDEXTERNALITEM T4 ON ((T4.PARTITION=5637144576) AND ((T2.ECORESPRODUCT=T4.ECORESPRODUCT) AND (T4.ECORESDISTINCTPRODUCTVARIANT=@P1))) CROSS JOIN HCMWORKER T5 CROSS JOIN DIRPARTYTABLE T6 CROSS JOIN DIRPARTYTABLE T7 CROSS JOIN VENDTABLE T8 CROSS JOIN ECORESPRODUCT T9 CROSS JOIN ECORESPRODUCTCATEGORY T10 CROSS JOIN ECORESCATEGORY T11 WHERE (((T1.PARTITION=5637144576) AND (T1.DATAAREAID=N''087'')) AND (T1.DATAAREAID=@P2)) AND ((T2.PARTITION=5637144576) AND ((T2.ECORESPRODUCT=T1.PRODUCT) AND (T2.SGE=@P3))) AND ((T3.PARTITION=5637144576) AND ((T3.ECORESREFORDERNUM=T2.ECORESREFORDERNUM) AND (T3.LANGUAGEID=@P4))) AND ((T5.PARTITION=5637144576) AND (T5.RECID=T2.PRODUCTMANAGER)) AND (((T6.PARTITION=5637144576) AND (T6.INSTANCERELATIONTYPE IN (@P5,@P6,@P7,@P8,@P9,@P10,@P11) )) AND (T6.RECID=T5.PERSON)) AND (((T7.PARTITION=5637144576) AND (T7.INSTANCERELATIONTYPE IN (@P12,@P13,@P14,@P15,@P16,@P17,@P18) )) AND (T1.EXTERNALVENDPARTY=T7.RECID)) AND (((T8.PARTITION=5637144576) AND (T8.DATAAREAID=N''087'')) AND ((T7.RECID=T8.PARTY) AND (T8.DATAAREAID=@P19))) AND (((T9.PARTITION=5637144576) AND (T9.INSTANCERELATIONTYPE IN (@P20,@P21,@P22) )) AND (T9.RECID=T1.PRODUCT)) AND ((T10.PARTITION=5637144576) AND (T10.PRODUCT=T9.RECID)) AND (((T11.PARTITION=5637144576) AND (T11.INSTANCERELATIONTYPE IN (@P23,@P24) )) AND (T11.RECID=T10.CATEGORY))',@p5 output,@p6 output,@p7 output,0,N'087',5637146082,N'de',41,2303,2377,2975,2978,5329,6886,41,2303,2377,2975,2978,5329,6886,N'087',3265,3266,3267,2665,4423
select @p1, @p2, @p5, @p6, @p7

पहली चीज़ जो मैंने देखी, वह यह है कि यह क्वेरी एक कर्सर का उपयोग कर रही थी। जिज्ञासा से बाहर मैंने कथन को कॉपी किया और प्रबंधन स्टूडियो में कर्सर के सामान के बिना निष्पादित किया (मुझे यह स्वीकार करना होगा कि मैंने क्वेरी के लिए मापदंडों को बदल दिया है ताकि मैं इसे चला सकूं)। SSMS के भीतर क्वेरी 30 सेकंड में समाप्त हो गई। बहुत तेज नहीं है, लेकिन फिर भी कर्सर विकल्प से भी तेज है।

यहाँ मैं आपको दोनों योजनाएँ प्रदान करता हूँ:

कर्सर के बिना योजना अभी भी बहुत खराब योजना है लेकिन यह बहुत बेहतर है। मेरा सवाल यहाँ है: क्या कोई मुझे समझा सकता है कि कर्सर संस्करण को 53 मिलियन रीड की आवश्यकता क्यों है?

कर्सर के साथ क्वेरी के लिए आँकड़े:

Duration    CPU         Reads       Writes  Est Rows    Actual Rows
1.396.212   1.379.157   53.270.895  3.878   30          2

कर्सर के बिना क्वेरी के लिए आँकड़े:

Duration    CPU         Reads       Writes  Est Rows    Actual Rows
23.337      1.703       665.113     13      4.287       34.813

2 के बजाय 34,813 पंक्तियों को प्राप्त करना अजीब लगता है; लेकिन मुझे पूरा यकीन है कि मैं सही मापदंडों में भरा हूं। मैंने सोचा कि यह शायद SQL सेंट्री का एक अजीब चुटकुला था क्योंकि मैंने अभी-अभी वहां से आंकड़े कॉपी किए हैं।

मुझे आशा है कि मैं आपको आपके लिए सभी आवश्यक जानकारी प्रदान कर सकता हूं। इसके अलावा, अगर किसी के पास कुछ अच्छे रीडिंग हैं, तो बेहतर समझ वाले कर्सर हैं जो बहुत अच्छे होंगे।

जवाबों:


10

सबसे पहले, यह मुझे आश्चर्यचकित करता है कि SQL संतरी से दोनों प्रश्नों की वास्तविक संख्या कम या ज्यादा नहीं है।

दूसरा। यह बताना मुश्किल है कि वास्तविक योजना के बिना एक कर्सर के साथ योजना में आपके अनुमान कितने सही हैं लेकिन कुछ चीजें मेरे सामने हैं। (पुनश्च: वास्तविक योजना प्राप्त करने के लिए यहां मेरे उत्तर का संदर्भ लें )।

कहा जा रहा है, कुछ चीजें हैं जो आपके अनुमानित योजना से नोट की जा सकती हैं।

पैरामीरिजेशन के कारण बेजोड़ इंडेक्स के बारे में चेतावनी है । पैराट्राइज़ेशन को हटाना ताकि SQL सर्वर उन बेजोड़ का उपयोग कर सकता है जो नाटकीय रूप से I / O में सुधार कर सकते हैं।

2 योजनाओं के बीच पंक्तियों की अनुमानित संख्या नाटकीय रूप से भी बंद है। एक कर्सर के साथ आपकी योजना में 11. वेंडेक्सटेरिटेम से पंक्तियों की अनुमानित संख्या है। एक कर्सर के बिना आपकी योजना में आपके पास लगभग 200K की पंक्तियों की अनुमानित और वास्तविक संख्या है। यदि आपका 200K रिकॉर्ड वास्तव में उस स्पूल ऑपरेटर में चला जाता है जो दर्दनाक हो सकता है।

सभी ऑपरेटरों के बेतहाशा अलग-अलग अनुमान हैं (एक कर्सर के साथ योजना में बहुत छोटा), इसलिए हो सकता है कि आपकी योजना को विभिन्न पैरामीटर मानों के साथ संकलित और कैश किया गया हो जो आप बिना कर्सर के क्वेरी में उपयोग कर रहे हैं। ( पैरामीटर सूँघने के रूप में जाना जाता है )

अनुक्रमणिका की तलाश में एक बहुत ही अजीब विकल्प है + आविष्कार तालिका पर महत्वपूर्ण खोज। योजना typeIdx का उपयोग कर रही है और तब संकुल अनुक्रमणिका (itemidx) के लिए मुख्य लुकअप करती है। यदि आपका अनुमान बंद है और SQL सर्वर को कई महत्वपूर्ण लुकअप करने हैं जो बहुत सारे IO को भी समझा सकते हैं। मैं बिना किसी कर्सर के आपकी योजना के स्टॉपिडेक्स से परिचित नहीं हूं, लेकिन ऐसा लगता है जैसे यह कवर कर रहा है ताकि आपके द्वारा प्रदान किए गए मापदंडों के लिए शायद एक बेहतर विकल्प हो। मुझे लगता है कि यह टाइपिडेक्स को चुना क्योंकि यह बहुत संकरा है लेकिन यह अलग-अलग संकलन समय मूल्यों के कारण हो सकता है जो आप समस्याग्रस्त निष्पादन के साथ प्रदान कर रहे हैं।

संक्षेप में, मैं इस क्वेरी के लिए AX में पैराट्राइज़ेशन को हटा दूंगा ताकि यह वास्तविक मानों के साथ एक योजना तैयार करे ताकि यह SSMS में योजना (और निष्पादन समय) के अनुसार "बेहतर" अनुक्रमित हो। यह SQL सर्वर को फ़िल्टर किए गए अनुक्रमित का उपयोग करने की भी अनुमति देगा। ऐसा करने के लिए, डेवलपर के पास एप्लिकेशन कोड में forceliteralsकीवर्ड जोड़ें जहां यह क्वेरी निष्पादित होती है और देखें कि क्या होता है।

यह शायद अभी भी आपको एक ऐसी क्वेरी के साथ छोड़ देगा जिसमें 30 सेकंड लगते हैं (जो आपके पास SSMS में है) लेकिन यह सिर्फ ट्यूनिंग की बात है। आपकी योजनाओं में अनुक्रमणिका चेतावनियाँ याद आ रही हैं और मुझे लगता है कि ecoresproductordernum.sge पर एक सूचकांक उदाहरण के लिए मदद कर सकता है, लेकिन मैं उन तालिकाओं को नहीं जानता और लगता है कि वे अनुकूलन द्वारा जोड़े गए हैं। सामान्य ट्यूनिंग सिद्धांत यहां मदद करेंगे लेकिन यह संभवतः इस उत्तर के लिए बहुत व्यापक होगा (अनुक्रमणिका को कवर करना, ...)


इससे मेरी समस्या हल हो गई। हमें वास्तव में दो समस्याएं थीं: पैरामीटर सूँघना और फ़िल्टर करना प्रेरित करता है। हमने AX में कुछ संबंधों को छोड़ दिया, इसलिए एप्लिकेशन ने इस अजीब को "DirPartyTable के लिए क्लॉज" में उत्पन्न किया। कहानी का अंत: सारणी संबंधों को कभी न छोड़ें :)
हंस वडेर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.