एक्सटेंडेड इवेंट्स पर मेरे द्वारा दिए जाने वाले प्रत्येक प्रेजेंटेशन में, मैं एक्सटेंडेड इवेंट्स में फ़िल्टरिंग और ट्रेस में फ़िल्टरिंग के बीच सबसे बड़े अंतरों में से एक को समझाने और समझाने की कोशिश करता हूँ; तथ्य यह है कि विधेय आदेश विस्तृत घटनाओं में मायने रखता है। अधिकांश समय मैं विस्तारित घटनाओं में विधेय मूल्यांकन के शॉर्ट-सर्किटिंग के बारे में बात कर रहा हूं, और निष्पादन कार्य पर नियंत्रण वापस करने के लिए जितनी जल्दी हो सके घटना को विफल तार्किक मूल्यांकन करने की कोशिश कर रहा हूं। मैं हाल ही में अपने एक उदाहरण ईवेंट सत्र के साथ काम कर रहा था जिसका उपयोग मैं प्रस्तुतियों में करता हूं जो विस्तारित ईवेंट में विधेय क्रम के एक अन्य महत्वपूर्ण पहलू को प्रदर्शित करता है।
विस्तारित घटनाओं के भीतर पाठ्य विधेय तुलनित्र होते हैं जो किसी घटना के लिए फ़िल्टरिंग मानदंड की अधिक जटिल परिभाषाओं की अनुमति देते हैं। इनमें से कुछ वास्तव में एक आंतरिक स्थिति बनाए रखते हैं, जबकि सर्वर पर ईवेंट सत्र शुरू होता है, उदाहरण के लिए package0.greater_than_max_uint64 और package0.less_than_min_uint64 तुलनित्र। एक विधेय स्रोत तत्व, package0.counter भी है, जो ईवेंट सत्र शुरू होने पर एक आंतरिक स्थिति भी बनाए रखता है। विस्तारित घटनाओं में विधेय बनाए रखने वाले राज्य के लिए, सबसे महत्वपूर्ण विचारों में से एक यह है कि जब भी राज्य की भविष्यवाणी को बनाए रखने वाले राज्य का मूल्यांकन किया जाता है, तब आंतरिक स्थिति बदल जाती है, न कि जब घटना पूरी तरह से आग लगती है। इसे प्रदर्शित करने के लिए, आइए package0.greater_than_max_uint64 टेक्स्टुअल विधेय तुलनित्र के उदाहरण उपयोग पर एक नज़र डालें। पहले हमें एक संग्रहीत कार्यविधि बनाने की आवश्यकता होगी जिसे हम निष्पादन अवधि को नियंत्रित कर सकते हैं:
USE AdventureWorks2012
GO
IF OBJECT_ID(N'StoredProcedureExceedsDuration') IS NOT NULL
DROP PROCEDURE dbo.StoredProcedureExceedsDuration;
GO
CREATE PROCEDURE dbo.StoredProcedureExceedsDuration
( @WaitForValue varchar(12) = '00:00:00:050')
AS
WAITFOR DELAY @WaitForValue;
GO फिर हमें sqlserver.module_end ईवेंट का उपयोग करके संग्रहीत कार्यविधि के निष्पादन को ट्रैक करने के लिए एक ईवेंट सत्र बनाने की आवश्यकता होगी, और ईवेंट द्वारा प्रदान किए गए object_id और source_database_id कॉलम पर निष्पादन को फ़िल्टर करना होगा। हम अवधि कॉलम के विरुद्ध package0.greater_than_max_uint64 टेक्स्टुअल तुलनित्र का उपयोग करके एक फ़िल्टर भी परिभाषित करेंगे, जो कि 1000000 या एक सेकंड की प्रारंभिक स्थिति के साथ विस्तारित ईवेंट में माइक्रोसेकंड में है। विधेय में इस जोड़ के साथ, घटना केवल तभी सक्रिय होगी जब अवधि 1000000 माइक्रोसेकंड के प्रारंभिक मान से अधिक हो जाएगी, और फिर विधेय नए राज्य मूल्य को आंतरिक रूप से संग्रहीत करेगा, ताकि घटना तब तक पूरी तरह से फिर से सक्रिय न हो जब तक कि अवधि 1000000 माइक्रोसेकंड से अधिक न हो जाए। नया आंतरिक राज्य मूल्य। एक बार जब हम इवेंट सेशन बनाते हैं, जो इस मामले में डायनेमिक SQL का उपयोग करता है क्योंकि हम SQL सर्वर में DDL स्टेटमेंट में पैरामीटराइजेशन का उपयोग नहीं कर सकते हैं, इसे सर्वर पर शुरू किया जाएगा और हम अपनी सैंपल स्टोर की गई प्रक्रिया को चला सकते हैं और कई बार निष्पादन अवधि को नियंत्रित कर सकते हैं। यह देखने के लिए कि घटना हमारे विधेय के साथ कैसे सक्रिय हुई।
IF EXISTS(SELECT *
FROM sys.server_event_sessions
WHERE name='StatementExceedsLastDuration')
DROP EVENT SESSION [StatementExceedsLastDuration] ON SERVER;
GO
-- Build the event session using dynamic SQL to concatenate the database_id
-- and object_id in the DDL, parameterization is not allowed in DDL!
DECLARE @ObjectID NVARCHAR(10) = OBJECT_ID('StoredProcedureExceedsDuration'),
@DatabaseID NVARCHAR(10) = DB_ID('AdventureWorks2012');
DECLARE @SqlCmd NVARCHAR(MAX) ='
CREATE EVENT SESSION [StatementExceedsLastDuration] ON SERVER
ADD EVENT sqlserver.module_end(
SET collect_statement = 1
WHERE (object_id = ' + @ObjectID + ' AND
source_database_id = ' + @DatabaseID + ' AND
package0.greater_than_max_uint64(duration, 1000000)))
ADD TARGET package0.ring_buffer(SET max_events_limit=10);'
EXECUTE(@SqlCmd)
ALTER EVENT SESSION [StatementExceedsLastDuration]
ON SERVER
STATE=START;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration '00:00:01.000';
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration '00:00:02.000';
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration '00:00:01.000';
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration; यदि आप SQLskills.com पर मेरा ब्लॉग पढ़ते हैं, तो आप शायद जानते हैं कि मैं कई कारणों से विस्तृत ईवेंट में ring_buffer लक्ष्य का उपयोग करने का बड़ा प्रशंसक नहीं हूं। इस सीमित डेटा संग्रह के लिए, और तथ्य यह है कि घटना सत्र इसे अधिकतम दस घटनाओं तक सीमित करता है, यह घटना के व्यवहार को प्रदर्शित करने के लिए एक आसान लक्ष्य है, लेकिन हमें अभी भी घटनाओं के लिए एक्सएमएल को मैन्युअल रूप से टुकड़े करना होगा परिणाम देखें।
-- Shred events out of the target
SELECT
event_data.value('(@name)[1]', 'nvarchar(50)') AS event_name,
event_data.value('(@timestamp)[1]', 'datetime2') AS [timestamp],
event_data.value('(data[@name="duration"]/value)[1]', 'bigint') as duration,
event_data.value('(data[@name="statement"]/value)[1]', 'varchar(max)') as [statement]
FROM ( SELECT CAST(target_data AS xml) AS TargetData
FROM sys.dm_xe_sessions AS s
INNER JOIN sys.dm_xe_session_targets AS t
ON s.address = t.event_session_address
WHERE s.name = N'StatementExceedsLastDuration'
AND t.target_name = N'ring_buffer' ) AS tab
CROSS APPLY TargetData.nodes (N'RingBufferTarget/event') AS evts(event_data); ऊपर दिए गए कोड को चलाने के परिणामस्वरूप केवल 2 ईवेंट होंगे, एक एक सेकंड के लिए, और फिर दूसरा दो सेकंड के निष्पादन के लिए। संग्रहीत कार्यविधि के अन्य निष्पादन विधेय में माइक्रोसेकंड में निर्दिष्ट प्रारंभिक एक सेकंड की अवधि के फ़िल्टर से कम होते हैं, और फिर अंतिम एक सेकंड का निष्पादन तुलनित्र द्वारा दो सेकंड के संग्रहीत राज्य मान की तुलना में अवधि में छोटा होता है। यह घटना संग्रह का अपेक्षित व्यवहार है, लेकिन अगर हम विधेय क्रम को बदलते हैं ताकि package0.greater_than_max_uint64(अवधि, 1000000) फ़िल्टर पहले विधेय क्रम में होता है, और एक दूसरी संग्रहीत प्रक्रिया बनाते हैं जिसे हम तीन की अवधि के साथ निष्पादित करते हैं सेकंड पहले, हमें कोई ईवेंट बिल्कुल नहीं मिलेगा।
USE AdventureWorks2012
GO
IF OBJECT_ID(N'StoredProcedureExceedsDuration') IS NOT NULL
DROP PROCEDURE dbo.StoredProcedureExceedsDuration;
GO
CREATE PROCEDURE dbo.StoredProcedureExceedsDuration
( @WaitForValue varchar(12) = '00:00:00:050')
AS
WAITFOR DELAY @WaitForValue;
GO
IF OBJECT_ID(N'StoredProcedureExceedsDuration2') IS NOT NULL
DROP PROCEDURE dbo.StoredProcedureExceedsDuration2;
GO
CREATE PROCEDURE dbo.StoredProcedureExceedsDuration2
( @WaitForValue varchar(12) = '00:00:00:050')
AS
WAITFOR DELAY @WaitForValue;
GO
IF EXISTS(SELECT *
FROM sys.server_event_sessions
WHERE name='StatementExceedsLastDuration')
DROP EVENT SESSION [StatementExceedsLastDuration] ON SERVER;
GO
-- Build the event session using dynamic SQL to concatenate the database_id
-- and object_id in the DDL, parameterization is not allowed in DDL!
DECLARE @ObjectID NVARCHAR(10) = OBJECT_ID('StoredProcedureExceedsDuration'),
@DatabaseID NVARCHAR(10) = DB_ID('AdventureWorks2012');
DECLARE @SqlCmd NVARCHAR(MAX) ='
CREATE EVENT SESSION [StatementExceedsLastDuration] ON SERVER
ADD EVENT sqlserver.module_end(
SET collect_statement = 1
WHERE (package0.greater_than_max_uint64(duration, 1000000) AND
object_id = ' + @ObjectID + ' AND
source_database_id = ' + @DatabaseID + '))
ADD TARGET package0.ring_buffer(SET max_events_limit=10);'
EXECUTE(@SqlCmd)
ALTER EVENT SESSION [StatementExceedsLastDuration]
ON SERVER
STATE=START;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration2 '00:00:03.050';
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration '00:00:01.050';
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration;
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration '00:00:02.050';
EXECUTE AdventureWorks2012.dbo.StoredProcedureExceedsDuration; इस मामले में, क्योंकि तुलनित्र बनाए रखने वाला राज्य पहले विधेय क्रम में होता है, इसके आंतरिक मूल्य को दूसरी संग्रहीत प्रक्रिया के तीन सेकंड के निष्पादन से बढ़ा दिया जाता है, भले ही घटना बाद में विधेय के ऑब्जेक्ट_आईडी फ़िल्टर को विफल कर देती है और पूरी तरह से आग नहीं लगती है। यह व्यवहार राज्य के हर एक के साथ होता है जो विस्तारित घटनाओं में विधेय बनाए रखता है। मैंने पहले इस व्यवहार को package0.counter विधेय स्रोत कॉलम के साथ खोजा था, लेकिन यह महसूस नहीं किया कि व्यवहार विधेय के किसी भी भाग के लिए होता है जो एक राज्य को बनाए रखता है। जैसे ही विधेय के उस हिस्से का मूल्यांकन किया जाता है, आंतरिक स्थिति बदल जाएगी। इस कारण से, कोई भी विधेय फ़िल्टर जो राज्य को बदलता है या बनाए रखता है, विधेय परिभाषा का पूर्ण अंतिम भाग होना चाहिए ताकि यह सुनिश्चित किया जा सके कि यह केवल राज्य को आंतरिक रूप से संशोधित करता है जब सभी विधेय स्थितियों का मूल्यांकन पारित हो जाता है।