क्या ट्रिगर हर बार संकलन करता है?


22

हम एक सर्वर का समस्या निवारण कर रहे हैं जिसमें उच्च CPU उपयोग है। यह जानने के बाद कि प्रश्न वास्तव में पैदा नहीं कर रहे थे, हमने संकलन देखना शुरू किया।

प्रदर्शन मॉनीटर 50 संकलनों / सेकंड से कम और 15 पुनरावर्ती / सेकंड से कम दिखा रहा है।

संकलन की तलाश में XE सत्र चलाने के बाद, हम प्रति सेकंड हजारों संकलन देख रहे हैं।

यह प्रणाली ऑडिट परिवर्तनों के लिए ट्रिगर का उपयोग कर रही है। अधिकांश संकलन ट्रिगर के कारण होते हैं। ट्रिगर संदर्भ sysinos_tran_active_transactions।

हमारा पहला विचार यह था कि शायद एक ट्रिगर में DMV को संदर्भित करने से यह हर बार संकलित हो जाएगा, या शायद यह विशिष्ट DMV इसका कारण होगा। इसलिए मैंने उस सिद्धांत का परीक्षण शुरू किया। यह प्रत्येक बार संकलित करता है, लेकिन मैंने यह नहीं जांचा था कि ट्रिगर हर बार ट्रिगर होने पर संकलित होता है जब यह DMV को संदर्भित नहीं करता है और इसके बजाय एक मान को हार्डकोड करता है। यह ट्रिगर होने पर भी हर बार संकलन कर रहा था। ट्रिगर छोड़ने से संकलन बंद हो जाता है।

  1. हम संकलनों को ट्रैक करने के लिए एक XE सत्र में sqlserver.query_pre_execution_showplan का उपयोग कर रहे हैं। क्यों वहाँ और PerfMon काउंटर के बीच एक विसंगति है?
  2. क्या यह सामान्य है कि आपको ट्रिगर रन के दौरान हर बार एक संकलन घटना मिलती है?

रेप्रो स्क्रिप्ट:

CREATE TABLE t1 (transaction_id int, Column2 varchar(100));
CREATE TABLE t2 (Column1 varchar(max), Column2 varchar(100));
GO

CREATE TRIGGER t2_ins
ON t2
AFTER INSERT
AS

INSERT INTO t1
SELECT (SELECT TOP 1 transaction_id FROM sys.dm_tran_active_transactions), Column2
FROM inserted;
GO

--Both of these show compilation events
INSERT INTO t2 VALUES ('row1', 'value1');
INSERT INTO t2 VALUES ('row2', 'value2');
GO

ALTER TRIGGER t2_ins
ON t2
AFTER INSERT
AS

INSERT INTO t1
SELECT 1000, Column2
FROM inserted;
GO

--Both of these show compilation events
INSERT INTO t2 VALUES ('row3', 'value3');
INSERT INTO t2 VALUES ('row4', 'value4');

DROP TRIGGER t2_ins;

--These do not show compilation events
INSERT INTO t2 VALUES ('row5', 'value5');
INSERT INTO t2 VALUES ('row6', 'value6');

DROP TABLE t1, t2;

जवाबों:


20

XE ईवेंट का उपयोग किया जा रहा है जिससे आपको लगता है कि ट्रिगर गलत तरीके से हो रहा है, जो वास्तव में हर निष्पादन को संकलित कर रहा है। दो विस्तारित घटनाएँ हैं query_pre_execution_showplan और query_post_compilation_showplan जिनके समान विवरण हैं, लेकिन एक महत्वपूर्ण शब्द से भिन्न हैं:

query_pre_execution_showplan

SQL स्टेटमेंट संकलित होने के बाद होता है। यह घटना क्वेरी के अनुकूलित होने पर उत्पन्न होने वाली अनुमानित क्वेरी योजना का XML प्रतिनिधित्व लौटाती है । इस घटना का उपयोग करने से एक महत्वपूर्ण प्रदर्शन ओवरहेड हो सकता है इसलिए इसका उपयोग केवल तब किया जाना चाहिए जब समस्या निवारण या समय की संक्षिप्त अवधि के लिए विशिष्ट समस्याओं की निगरानी करें।

query_post_compilation_showplan

SQL स्टेटमेंट संकलित होने के बाद होता है। यह ईवेंट, क्वेरी के संकलित होने पर उत्पन्न होने वाली अनुमानित क्वेरी योजना का XML प्रतिनिधित्व लौटाता है । इस घटना का उपयोग करने से एक महत्वपूर्ण प्रदर्शन ओवरहेड हो सकता है इसलिए इसका उपयोग केवल तब किया जाना चाहिए जब समस्या निवारण या समय की संक्षिप्त अवधि के लिए विशिष्ट समस्याओं की निगरानी करें।

घटनाएँ विवरण में बिल्कुल समान नहीं हैं और आपके रेप्रो का उपयोग करके आगे के परीक्षण से अलग-अलग समय पर होती हैं। एक बहुत बड़ी घटना सत्र परिभाषा का उपयोग करते हुए, यह देखना आसान है कि वास्तव में संकलन कहां हो रहा है।

यहाँ छवि विवरण दर्ज करें

यहां आप सम्मिलित विवरणों के लिए पहला संकलन देख सकते हैं क्योंकि तैयार योजनाएं हरे बॉक्स में ऑटो-पैरामीटर की जा रही हैं। ट्रिगर को लाल बॉक्स में संकलित किया गया है और योजना को कैश में डाला गया है जैसा कि sp_cache_insert ईवेंट द्वारा दिखाया गया है। फिर नारंगी बॉक्स में ट्रिगर निष्पादन कैश हिट हो जाता है और बैच में दूसरे INSERT स्टेटमेंट के लिए ट्रिगर योजना का पुन: उपयोग करता है, इसलिए यह INSERT कमांड के प्रत्येक निष्पादन को संकलित नहीं कर रहा है और योजना का पुन: उपयोग नहीं किया जाता है जैसा कि आप spc -cache_hit घटना के साथ देख सकते हैं ट्रिगर के लिए।

यदि हम पहले निष्पादन के बाद फिर से व्यक्तिगत रूप से दो INSERT बयान चलाते हैं, तो ट्रिगर फिर से संकलन नहीं करता है जैसा कि नीचे दी गई घटनाओं में दिखाया गया है:

यहाँ छवि विवरण दर्ज करें

यहां पहला बयान कैश में स्टेटमेंट के तैयार ऑटो-पैरामीटरेड संस्करण के लिए कैश हिट का सामना करता है, लेकिन एडहॉक बैच के लिए एक मिस जो प्रस्तुत किया गया था। ट्रिगर कैश हिट हो जाता है और फिर से संकलन नहीं करता है जैसा कि घटनाओं के लाल ब्लॉक में दिखाया गया है। घटनाओं का हरा ब्लॉक एक अलग बैच के रूप में चलाए जाने वाले दूसरे INSERT बयान के लिए इस व्यवहार को दोहराता है। हालांकि, हर मामले में आप अभी भी query_pre_execution_showplan घटना सक्रियण देखने के जो मैं कर सकते हैं केवल जा रहा है में अंतर करने के लिए विशेषता अनुकूलित बनाम संकलित घटना के विवरण में है, लेकिन ट्रिगर के रूप में की घटनाओं के इन श्रृंखला के द्वारा दिखाया हर निष्पादन के लिए संकलन नहीं है।


यदि आप पहले स्क्रीनशॉट को देखते हैं, तो संग्रहित अनचाहे sql_batch_statistics इवेंट संग्रह में है, लेकिन कैश क्लियर होने पर केवल sql बैच के पहले निष्पादन के लिए फायर करता है और INSERTs के लिए ऑटो-पैरामीटर प्लान योजना कैश में नहीं है। उसके बाद बिना पढ़े_sql_batch_statistics घटना फिर से आग नहीं लगाती है।
जोनाथन केहियास

Query_post_compilation_showplan ने ट्रिगर्स पर बस कुछ संकलन दिखाए, लेकिन दूसरे ईवेंट पर हम जो बड़े पैमाने पर देख रहे थे, वह नहीं। हमें query_post_compilation_showplan के साथ कुछ दिलचस्प नगेट्स मिले। जानकारी के लिए धन्यवाद, जोनाथन!
तारा किन्नर

13

नहीं। ट्रिगर हमेशा recompiled नहीं हैं। हालांकि, सरल क्वेरी स्टेटमेंट, उनकी योजनाओं को कैश नहीं किया जाता है और इसलिए उन्हें हमेशा recompiled किया जाएगा।

यदि सम्मिलित या हटाए गए परिवर्तनों में पंक्तियों की संख्या में परिवर्तन होता है, तो ट्रिगर पुन: व्यवस्थित हो जाते हैं। देखें: https://technet.microsoft.com/en-us/library/ms181055.aspx

मुझे नहीं पता कि उनके एक्सवेन्स में भी ऐसा ही है, लेकिन एसक्यूएल ट्रेस में, एक recompile में एक इवेंट सबक्लास है जो आपको बताता है कि यह क्यों recompiled था। उसी कड़ी में ऊपर बताया गया है।


1
हम पुनर्मिलन के बजाय संकलन देख रहे थे। हम सर्वर को कल देखने जा रहे हैं और जांचते हैं कि क्या यह एक साधारण क्वेरी स्टेटमेंट होने के कारण है या यदि यह पंक्तियों की संख्या के कारण है। धन्यवाद!
तारा किसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.