Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

प्रोएक्टिव SQL सर्वर स्वास्थ्य जांच, भाग 5:सांख्यिकी प्रतीक्षा करें

SQLskills टीम को प्रतीक्षा आँकड़े पसंद हैं। यदि आप इस ब्लॉग पर पोस्ट देखते हैं (घुटने-जर्क प्रतीक्षा सांख्यिकी पर पॉल की पोस्ट देखें) और SQLskills साइट पर, आप हम सभी की पोस्ट देखेंगे जो प्रतीक्षा आँकड़ों के मूल्य पर चर्चा करते हैं, हम क्या खोजते हैं, और एक विशेष क्यों प्रतीक्षा एक मुद्दा है। पॉल इसके बारे में सबसे अधिक लिखते हैं, लेकिन हम सभी आमतौर पर किसी प्रदर्शन समस्या का निवारण करते समय प्रतीक्षा आंकड़ों से शुरू करते हैं। सक्रिय होने के संदर्भ में इसका क्या अर्थ है?

किसी प्रदर्शन समस्या के दौरान प्रतीक्षा आँकड़ों का क्या अर्थ है, इसकी पूरी तस्वीर प्राप्त करने के लिए, आपको पता होना चाहिए कि आपकी सामान्य प्रतीक्षाएँ क्या हैं। इसका मतलब है कि इस जानकारी को सक्रिय रूप से कैप्चर करना और उस आधार रेखा को संदर्भ के रूप में उपयोग करना। यदि आपके पास यह डेटा नहीं है, तो जब कोई प्रदर्शन समस्या होती है, तो आपको पता नहीं चलेगा कि क्या आपके वातावरण में PAGELATCH प्रतीक्षा विशिष्ट है (काफी संभव है) या यदि आपके पास जोड़े गए कुछ नए कोड के कारण अचानक tempdb से संबंधित कोई समस्या है ।

प्रतीक्षा सांख्यिकी डेटा

मैंने पहले एक स्क्रिप्ट प्रकाशित की है जिसका उपयोग मैं प्रतीक्षा आंकड़ों को पकड़ने के लिए करता हूं, और यह एक ऐसी स्क्रिप्ट है जिसका उपयोग मैं ग्राहकों के लिए लंबे समय से कर रहा हूं। हालाँकि, मैंने हाल ही में अपनी स्क्रिप्ट में बदलाव किए हैं और अपने तरीके में थोड़ा बदलाव किया है। मुझे समझाएं क्यों...

प्रतीक्षा आँकड़ों के पीछे मूल आधार यह है कि SQL सर्वर हर बार किसी थ्रेड को "कुछ" के लिए प्रतीक्षा करने के लिए ट्रैक कर रहा है। डिस्क से एक पेज पढ़ने की प्रतीक्षा कर रहे हैं? PAGEIOLATCH_XX प्रतीक्षा करें। लॉक दिए जाने की प्रतीक्षा कर रहे हैं ताकि आप डेटा में संशोधन कर सकें? LCX_M_XXX प्रतीक्षा करें। स्मृति अनुदान की प्रतीक्षा कर रहा है ताकि कोई क्वेरी निष्पादित हो सके? RESOURCE_SEMAPHORE प्रतीक्षा करें। इन सभी प्रतीक्षाओं को sys.dm_os_wait_stats DMV में ट्रैक किया जाता है, और डेटा समय के साथ जमा होता है... यह प्रतीक्षा का एक संचयी प्रतिनिधि है।

उदाहरण के लिए, मेरे पास मेरे एक VM में SQL Server 2014 इंस्टेंस है जो आज सुबह लगभग 9:30 बजे से चालू है:

[sys] से
चुनें [sqlserver_start_time]।[dm_os_sys_info];

SQL सर्वर प्रारंभ समय

अब अगर मैं यह देखना चाहता हूं कि पॉल की लिपि का उपयोग करके मेरे प्रतीक्षा आंकड़े क्या दिखते हैं (याद रखें, अब तक संचयी), तो मैं देखता हूं कि TRACEWRITE मेरा वर्तमान "मानक" प्रतीक्षा है:

वर्तमान कुल प्रतीक्षा

ठीक है, अब पांच मिनट के tempdb विवाद का परिचय दें, और देखें कि यह मेरे समग्र प्रतीक्षा आंकड़ों को कैसे प्रभावित करता है। मेरे पास एक स्क्रिप्ट है जिसे जोनाथन ने पहले tempdb विवाद बनाने के लिए उपयोग किया है, और मैंने इसे सेट किया है ताकि यह 5 मिनट तक चले:

एडवेंचरवर्क्स2012 का उपयोग करें; गो डिक्लेयर करें @CurrentTime SMALLDATETIME =SYSDATETIME(), @EndTime SMALLDATETIME =DATEADD(MINUTE, 5, SYSDATETIME()); जबकि @CurrentTime <@EndTimeBEGIN IF OBJECT_ID('tempdb..# temp') ड्रॉप टेबल #temp शुरू नहीं है; एंड क्रिएट टेबल #temp (ProductID INT PRIMARY KEY, OrderQty INT, TotalDiscount MONEY, LineTotal MONEY, फिलर NCHAR(500) DEFAULT(N'') NOT NULL); INSERT INTO #temp(ProductID, OrderQty, TotalDiscount, LineTotal) सेलेक्ट sod.ProductID, SUM(sod.OrderQty), SUM(sod.LineTotal), SUM(sod.OrderQty + sod.UnitPriceDiscount) from Sales.SalesOrderDetail AS sod GROUP BY उत्पाद आयडी; DECLARE @ProductNumber NVARCHAR(25), @Name NVARCHAR(50), @TotalQty INT, @SalesTotal MONEY, @TotalDiscount MONEY; चुनें @ProductNumber =p.ProductNumber, @Name =p.Name, @TotalQty =t1.OrderQty, @SalesTotal =t1.LineTotal, @TotalDiscount =t1. Production से TotalDiscount.Product AS p जॉइन करें #temp AS t1 ON p.ProductID =t1.ProductID; सेट करें @CurrentTime =SYSDATETIME()END

मैंने इस स्क्रिप्ट को चलाने वाले 10 सत्र शुरू करने के लिए एक कमांड प्रॉम्प्ट का उपयोग किया, और साथ ही एक स्क्रिप्ट चलाई जिसने मेरे समग्र प्रतीक्षा आंकड़ों को कैप्चर किया, 5 मिनट की समय अवधि में प्रतीक्षा का एक स्नैपशॉट, और फिर समग्र प्रतीक्षा आंकड़े फिर से। सबसे पहले, एक छोटा सा रहस्य, चूंकि हम हर समय सौम्य प्रतीक्षा को अनदेखा करते हैं, इसलिए उन्हें एक तालिका में रखना उपयोगी हो सकता है ताकि आप किसी क्वेरी में बहिष्करण स्ट्रिंग की सूची को लगातार हार्ड-कोड करने के बजाय किसी ऑब्जेक्ट को संदर्भित कर सकें। तो:

 SQLskills_WaitStats का उपयोग करें; तालिका बनाएं dbo.WaitsToIgnore (प्रतीक्षा प्रकार SYSNAME प्राथमिक कुंजी); INSERT dbo.WaitsToIgnore(WaitType) VALUES(N'BROKER_EVENTHANDLER'), (N'BROKER_RECEIVE_WAITFOR'), (N'BROKER_TASK_STOP'), (N'BROKER_TO_FLUSH'), (N'BROKER_  INTHANDLER"), (N'CHKPT'), (N'CLR_AUTO_EVENT'), (N'CLR_MANUAL_EVENT'), (N'CLR_SEMAPHORE'), (N'DBMIRROR_DBM_EVENT'),     (N'DBMIUERROR_EVENTS_QUEUE'), (N'DBMIRROR_WORKER_",  N'DBMIRRORING_CMD'), (N'DIRTY_PAGE_POLL'), (N'DISPATCHER_QUEUE_SEMAPHORE'), (N'EXECSYNC'),   (N'FSAGENT'), (N'FT_IFTS_SCHEDULER_IDLE_WAIT"), (N'FT_IFTSHC_MUTEX'), (N'FT_IFTSHC_MUTEX') 'HADR_CLUSAPI_CALL'), (N'HADR_FILESTREAM_IOMGR_IOCOMPLETIO(N'), (N'HADR_LOGCAPTURE_WAIT'), (N'HADR_NOTIFICATION_DEQUEUE'), (N'HADR_TIMER_TASK'), (N'HADR_WORK"), (W _ (OURCEUE") N'LAZYWRITER_SLEEP'), (N'LOGMGR_QUEUE'), (N'ONDEMAND_TASK_QUEUE'), (N'PWAIT_ALL_COMPONENTS_INITIALIZED'), (N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP'), (N'N_SCK_QUEUE'), (N'QUERISKLE_CLEAN" 'RESOURCE_QUEUE' ), (N'SERVER_IDLE_CHECK'), (N'SLEEP_BPOOL_FLUSH'), (N'SLEEP_DBSTARTUP'), (N'SLEEP_DCOMSTARTUP'), (N'SLEEP_MASTERDBREADY'), (N'SLEEP_MASTERMDREADY"), (N'SLEEP_MASTERMDREADY'), (N'SLEEP_MASTERMDREADY') , (N'SLEEP_MSDBSTARTUP'), (N'SLEEP_SYSTEMTASK'),    (N'SLEEP_TASK'), (N'SLEEP_TEMPDBSTARTUP'), (N'SNI_HTTP_ACCEPT'), (N'SP_SERHVER_DIAGNOSTICS_SLETRACE_BUFFERSQL_SERHVER_DIAGNOSTICS_SLETRACE_), (N'FLUSHVER_DIAGNOSTICS_SLETRACE") (N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP'), (N'SQLTRACE_WAIT_ENTRIES'), (N'WAIT_FOR_RESULTS'), (N'WAITFOR'), (N'WAITFOR_TASKSHUTDOW (N'), (N'WAIT_XTP_HOST_WAIT_LOT_LO"), (N'WAIT_XTP_HOST_WAIT_WPT_LO'), (N'WAIT_XTP_HOST_WAIT_WPT_LO') , (N'WAIT_XTP_CKPT_CLOSE'),  (N'XE_DISPATCHER_JOIN'), (N'XE_DISPATCHER_WAIT'), (N'XE_TIMER_EVENT');

अब हम अपने इंतजार को पूरा करने के लिए तैयार हैं:

/* इंस्टेंस प्रारंभ समय कैप्चर करें (इस मामले में, प्रतीक्षा के बाद से समय जमा हो रहा है) */ [sys] से [sqlserver_start_time] चुनें। [dm_os_sys_info];GO /* वर्तमान समय प्राप्त करें */ SYSDATETIME() चुनें एएस [टेस्ट 1 से पहले]; /* अब तक की कुल प्रतीक्षा प्राप्त करें */ के साथ [प्रतीक्षा करें] AS(चुनें [प्रतीक्षा_प्रकार], [प्रतीक्षा_समय_एमएस] / 1000.0 एएस [प्रतीक्षा करें], ([प्रतीक्षा_समय_एमएस] - [सिग्नल_वेट_टाइम_एमएस]) / 1000.0 एएस [संसाधन], [सिग्नल_वेट_टाइम_एमएस] / 1000.0 AS [SignalS], [waiting_tasks_count] AS [WaitCount], 100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [प्रतिशत], ROW_NUMBER() OVER([wait_time_ms] DESC द्वारा ऑर्डर करें) AS [RowNum] sys.dm_os_wait_stats से जहां [wait_type] नहीं है (SQLskills_Waits.WaitsToIgnore से प्रतीक्षा प्रकार चुनें) और [waiting_tasks_count]> 0) MAX चुनें ([W1]। [wait_type]) AS [WaitType], CAST (MAX ([W1]) के रूप में। WaitS]) AS DECIMAL (16,2)) AS [Wait_S], CAST (MAX ([W1]। [ResourceS]) AS DECIMAL (16,2)) AS [Resource_S], CAST (MAX ([W1].[)। SignalS]) AS DECIMAL (16,2)) AS [Signal_S], MAX ([W1]। [WaitCount]) AS [WaitCount], CAST (MAX ([W1]। [Percentage]) AS DECIMAL (5,2) ) AS [प्रतिशत], CAST ((MAX ([W1]। [WaitS]) / MAX ([W1]। [WaitCount])) AS DECIMAL (16,4)) AS [AvgWait_S], CAST ((MAX ([ W1]। [संसाधन S]) / MAX ([W1]। [WaitCount])) AS DECIMAL (16,4)) AS [AvgRes_S], CAST ((MAX ([W1]। [SignalS]) / MAX ([W1]। [WaitCount) ])) दशमलव के रूप में (16,4)) के रूप में [औसत सिग_एस] से [प्रतीक्षा करता है] के रूप में [W1] आंतरिक शामिल हों [प्रतीक्षा करता है] [W2] पर [W2]। [RowNum] <=[W1]। [RowNum] GROUP द्वारा [W1]। -- प्रतिशत सीमाGO /* वर्तमान समय प्राप्त करें */ SYSDATETIME() AS [टेस्ट 2 से पहले] चुनें; /* 5 मिनट की अवधि में प्रतीक्षा का एक स्नैपशॉट कैप्चर करें */ IF EXISTS (चुनें * [tempdb] से। [sys]। [ऑब्जेक्ट्स] जहां [नाम] =N'##SQLskillsStats1') ड्रॉप टेबल [##SQLskillsStats1]; IF EXISTS (चुनें * [tempdb] से। , [max_wait_time_ms], [signal_wait_time_ms]INTO##SQLskillsStats1FROM sys.dm_os_wait_stats;जाओ प्रतीक्षा करें देरी से '00:05:00';जाओ चुनें [प्रतीक्षा_प्रकार], [प्रतीक्षा_कार्य_गणना], [समय_प्रतीक्षा_TO_MS_, [समय_मैक्स_समय_TO_ms], #SQLskillsStats2FROM sys.dm_os_wait_stats; [DiffWaits] AS के साथ जाएं (चुनें - प्रतीक्षा करें जो पहले स्नैपशॉट में नहीं थे [ts2]। [wait_type], [ts2]। [wait_time_ms], [ts2]। [signal_wait_time_ms], [ ts2]। Wait_type] IS NULL और [ts2] है। ], [ts2] [सिग्नल_वेट_टाइम_एमएस] - [टीएस 1]। [सिग्नल_वेट_टाइम_एमएस] एएस [सिग्नल_वेट_टाइम_एमएस], [टीएस 2]। ##SQLskillsStats1] AS [ts1] पर [ts2]। [प्रतीक्षा_प्रकार] =[ts1]। [प्रतीक्षा_प्रकार] जहां [ts1]। ]> 0 और [ts2]। [प्रतीक्षा_समय_एमएस] - [ts1]। ]) / 1000.0 AS [ResourceS], [Signal_wait_time_ms] / 1000.0 AS [SignalS], [waiting_tasks_count] AS [WaitCount], 100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [प्रतिशत], ROW_NUMBER() OVER([wait_time_ms] DESC द्वारा ऑर्डर करें) AS [RowNum] फ्रॉम [DiffWaits] जहां [wait_type] नहीं है (Select WaitType से SQLskills_WaitStats.dbo.WaitsToIgnore)) चुनें [W1]।[wait_type] AS [प्रतीक्षा प्रकार], CAST W1]। [प्रतीक्षा करें] दिसंबर के रूप में IMAL (16, 2)) AS [Wait_S], CAST ([W1]। [ResourceS] AS DECIMAL (16, 2)) AS [Resource_S], CAST ([W1]। [SignalS] AS DECIMAL (16, 2) ) AS [Signal_S], [W1]। [WaitCount] AS [WaitCount], CAST ([W1]। [प्रतिशत] दशमलव के रूप में (5, 2)) AS [प्रतिशत], CAST (([W1]। [प्रतीक्षा करें) / [W1]। [WaitCount]) AS DECIMAL (16, 4)) AS [AvgWait_S], CAST (([W1]। [ResourceS] / [W1]। [WaitCount]) AS DECIMAL (16, 4)) AS [AvgRes_S], CAST (([W1]। [SignalS] / [W1]। [WaitCount]) दशमलव के रूप में (16, 4)) AS [AvgSig_S] से [प्रतीक्षा करता है] AS [W1]INNER JOIN [प्रतीक्षा करता है] AS [ W2] पर [W2]। [RowNum] <=[W1]। [RowNum] ग्रुप बाय [W1]। [RowNum], [W1]। संसाधन एस], [डब्ल्यू1]। [सिग्नलएस], [डब्ल्यू1]। [प्रतीक्षा गणना], [डब्ल्यू1]। -- प्रतिशत थ्रेशोल्डGO -- क्लीनअप IF EXISTS (चुनें * [tempdb] से। [sys]। [ऑब्जेक्ट्स] जहां [name] =N'##SQLskillsStats1') ड्रॉप टेबल [##SQLskillsStats1]; IF EXISTS (चुनें * [tempdb] से। एएस [टेस्ट 1 के बाद]; /* फिर से कुल प्रतीक्षा प्राप्त करें */ के साथ [प्रतीक्षा करें] AS(चुनें [wait_type], [wait_time_ms] / 1000.0 AS [WaitS], ([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS], [signal_wait_time_ms] / 1000.0 AS [SignalS], [waiting_tasks_count] AS [WaitCount], 100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [प्रतिशत], ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum] FROM sys.dm_os_wait_stats जहां [प्रतीक्षा_प्रकार] नहीं है (SQLskills_WaitStats.dbo.WaitsToIgnore से प्रतीक्षा प्रकार चुनें) और [waiting_tasks_count]> 0) MAX चुनें ([W1]। [wait_type]) AS [WaitType], CAST (MAX ([WW1)]। [प्रतीक्षा करें]) दशमलव के रूप में (16,2)) के रूप में [प्रतीक्षा_एस], कास्ट (MAX ([W1]। [संसाधन]) दशमलव के रूप में (16,2)) AS [Resource_S], CAST (MAX ([W1])। [SignalS]) AS DECIMAL (16,2)) AS [Signal_S], MAX ([W1]। [WaitCount]) AS [WaitCount], CAST (MAX ([W1]। [Percentage]) AS DECIMAL (5,2) )) AS [प्रतिशत], CAST ((MAX ([W1]। [WaitS]) / MAX ([W1]। [WaitCount])) AS [AvgWait_S], CAST ((MAX ( [W1]। [Reso urceS])/MAX ([W1]। ])) दशमलव के रूप में (16,4)) के रूप में [औसत सिग_एस] से [प्रतीक्षा करता है] के रूप में [W1] आंतरिक शामिल हों [प्रतीक्षा करता है] [W2] पर [W2]। [RowNum] <=[W1]। [RowNum] GROUP द्वारा [W1]। -- प्रतिशत सीमाGO /* वर्तमान समय प्राप्त करें */ SYSDATETIME() AS [टेस्ट 2 के बाद] चुनें;

यदि हम आउटपुट को देखें, तो हम देख सकते हैं कि जब स्क्रिप्ट के 10 उदाहरण tempdb विवाद बनाने के लिए चल रहे थे, SOS_SCHEDULER_YIELD हमारा सबसे प्रचलित प्रतीक्षा प्रकार था, और हमारे पास PAGELATCH_XX प्रतीक्षा भी थी, जैसा कि अपेक्षित था:

परीक्षण से पहले, दौरान और परीक्षण के बाद सारांश की प्रतीक्षा करता है

यदि हम परीक्षण पूरा होने के बाद औसत प्रतीक्षा को देखते हैं, तो हम फिर से TRACEWRITE को उच्चतम प्रतीक्षा के रूप में देखते हैं, और हम SOS_SCHEDULER_YIELD को प्रतीक्षा के रूप में देखते हैं। पर्यावरण में और क्या चल रहा है, इस पर निर्भर करते हुए, यह प्रतीक्षा हमारे शीर्ष प्रतीक्षा में लंबे समय तक बनी रह सकती है या नहीं, और यह जांच के लिए प्रतीक्षा प्रकार के रूप में बबल हो भी सकती है और नहीं भी।

प्रतीक्षा सांख्यिकी को सक्रिय रूप से कैप्चर करना

डिफ़ॉल्ट रूप से, प्रतीक्षा के आंकड़े संचयी होते हैं . हाँ, आप उन्हें किसी भी समय DBCC SQLPERF का उपयोग करके साफ़ कर सकते हैं, लेकिन मुझे लगता है कि अधिकांश लोग नियमित रूप से ऐसा नहीं करते हैं, वे बस उन्हें जमा होने देते हैं। और यह ठीक है, लेकिन समझें कि यह आपके डेटा को कैसे प्रभावित करता है। यदि आप अपने इंस्टेंस को पैच करते समय केवल पुनरारंभ करते हैं, या जब कोई समस्या होती है (जो उम्मीद है कि शायद ही कभी होती है), तो वह डेटा महीनों के लिए जमा हो सकता है। आपके पास जितना अधिक डेटा होगा, छोटी विविधताओं को देखना उतना ही कठिन होगा… ऐसी चीज़ें जो प्रदर्शन संबंधी समस्याएं हो सकती हैं। यहां तक ​​​​कि जब आपके पास एक "बड़ी समस्या" है जो आपके पूरे सर्वर को कई मिनटों तक प्रभावित कर रही है, जैसा कि हमने यहां tempdb के साथ किया था, तो यह आपके डेटा में पर्याप्त बदलाव नहीं कर सकता है ताकि संचयी डेटा में पता लगाया जा सके। इसके बजाय, अभी वास्तव में क्या हो रहा है, यह देखने के लिए आपको डेटा को स्नैपशॉट करना होगा (इसे कैप्चर करें, कुछ मिनट प्रतीक्षा करें, इसे फिर से कैप्चर करें, और फिर डेटा को अलग करें) ।

इस प्रकार, यदि आप हर कुछ घंटों में केवल स्नैपशॉट प्रतीक्षा के आँकड़ों का स्नैपशॉट लेते हैं, तो आपके द्वारा एकत्र किया गया डेटा समय के साथ निरंतर एकत्रीकरण दिखाता है। आप कर सकते हैं स्नैपशॉट के बीच प्रदर्शन की समझ प्राप्त करने के लिए उन स्नैपशॉट को अलग करें, लेकिन मैं आपको एक बड़े डेटा सेट के खिलाफ इस कोड को लिखने से कह सकता हूं, यह एक दर्द है (लेकिन मैं एक देव नहीं हूं, इसलिए शायद यह आपके लिए आसान है )।

प्रतीक्षा आँकड़ों को कैप्चर करने का मेरा पारंपरिक तरीका पॉल की मूल स्क्रिप्ट का उपयोग करके हर कुछ घंटों में सिर्फ sys.dm_os_wait_stats को स्नैपशॉट करना था:

उपयोग [बेसलाइनडेटा];जाओ अगर मौजूद नहीं है (चुनें * [sys] से। [टेबल] जहां [नाम] =N'SQLskills_WaitStats_OldMethod') BEGIN TABLE [dbo]। पहचान (1,1) न्यूल नहीं, [कैप्चरडेट] [डेटाटाइम] न्यूल, [वेट टाइप] [नवरचर] (120) न्यूल, [वेट_एस] [दशमलव] (14, 2) न्यूल, [संसाधन_एस] [दशमलव] (14, 2) NULL, [Signal_S] [दशमलव] (14, 2) NULL, [वेटकाउंट] [बिगिन्ट] NULL, [प्रतिशत] [दशमलव] (4, 2) NULL, [AvgWait_S] [दशमलव] (14, 4) NULL , [AvgRes_S] [दशमलव] (14, 4) NULL, [AvgSig_S] [दशमलव] (14, 4) NULL); क्लस्टर इंडेक्स बनाएं [CI_SQLskills_WaitStats_OldMethod] ऑन [dbo]। ( [कैप्चरडेट], [प्रतीक्षा प्रकार], [प्रतीक्षा_एस], [संसाधन_एस], [सिग्नल_एस], [प्रतीक्षागणना], [प्रतिशत], [औसत प्रतीक्षा_एस], [औसत रेस (एस) [एवीजीएसआईजीएस]) EXEC ('के साथ) [wait_type], [wait_time_ms] / 1000.0 AS [WaitS], ([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS], [signal_wait_time_ms] / 1000.0 AS [SignalS], [wait_tasks_count] AS [Wait_tasks_count] चुनें * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [प्रतिशत], ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum] sys.dm_os_wait_stats से जहां [wait_type] SQL से नहीं है (Skill WaitType से SQL का चयन करें) .dbo.WaitsToIgnore)) चुनें GETDATE (), [W1]। [wait_type] AS [WaitType], CAST ([W1]। [WaitS] AS DECIMAL(14, 2)) AS [Wait_S], CAST ([W1]। [ResourceS] AS DECIMAL(14, 2)) AS [Resource_S], CAST ([W1]। [SignalS] AS DECIMAL(14, 2)) AS [Signal_S], [ डब्ल्यू1]। ]) दशमलव के रूप में (14, 4)) के रूप में [औसत प्रतीक्षा_एस], कास्ट (([W1]। [संसाधन] / [W1]। [प्रतीक्षा गणना]) दशमलव के रूप में (14, 4)) AS [AvgRes_S], CAST (( [W1]। [SignalS] / [W1]। [WaitCount]) दशमलव के रूप में (14, 4)) AS [AvgSig_S] से [वेट्स] AS [W1] इनर जॉइन [वेट्स] AS [W2] ऑन [W2]। [RowNum] <=[W1]। [RowNum] ग्रुप बाय [W1]। [SignalS], [W1]। [WaitCount], [W1]। [प्रतिशत] योग होने ([W2]। [प्रतिशत]) - [W1]। [प्रतिशत] <95;');

फिर मैं प्रत्येक स्नैपशॉट के लिए शीर्ष प्रतीक्षा को देखूंगा, उदाहरण के लिए:

चुनें [w]।[कैप्चरडेट] , [w]। ]से   [डीबीओ]। 60 ग्रुप बाय [कैप्चरडेट]) मी ऑन [डब्ल्यू]। 

मेरा नया, वैकल्पिक तरीका यह है कि हर घंटे या तो प्रतीक्षा आंकड़ों के दो स्नैपशॉट (स्नैपशॉट के बीच दो से तीन मिनट के साथ) को अलग किया जाए। यह जानकारी तब मुझे बताती है कि उस समय सिस्टम किसका इंतजार कर रहा था:

उपयोग करें [बेसलाइनडेटा];जाओ अगर मौजूद नहीं है (चुनें * से   [sys]। पहचान (1,1) न्यूल नहीं, [कैप्चरडेट] [डेटाटाइम] नॉट डिफॉल्ट (sysdatetime ()), [वेट टाइप] [नवरचर] (60) नॉट न्यूल, [वेट_एस] [दशमलव] (16, 2) न्यूल, [ Resource_S] [दशमलव] (16, 2) NULL, [Signal_S] [दशमलव] (16, 2) NULL, [वेटकाउंट] [बिगिन्ट] NULL, [प्रतिशत] [दशमलव] (5, 2) NULL, [AvgWait_S] [ दशमलव] (16, 4) NULL, [AvgRes_S] [दशमलव] (16, 4) NULL, [AvgSig_S] [दशमलव] (16, 4) NULL) ऑन [प्राथमिक]; [dbo] पर क्लस्टर इंडेक्स [CI_SQLskills_WaitStats] बनाएं। [SQLskills_WaitStats] ([कैप्चरडेट], [RowNum]);END /* शेड्यूल किए गए काम में इस्तेमाल करने के लिए क्वेरी .[sys].[ऑब्जेक्ट्स] जहां [नाम] =N'##SQLskillsStats1') ड्रॉप टेबल [##SQLskillsStats1]; IF EXISTS (चुनें * [tempdb] से। [waiting_tasks_count], [wait_time_ms], [max_wait_time_ms], [signal_wait_time_ms]INTO ##SQLskillsStats1FROM sys.dm_os_wait_stats;GO /* कुछ समय प्रतीक्षा करें */ WAITFOR DELAY '00:02:00' फिर से कैप्चर करें। */ चुनें [वेट_टाइप], [वेटिंग_टास्क_काउंट], [वेट_टाइम_एमएस], [मैक्स_वेट_टाइम_एमएस], [सिग्नल_वेट_टाइम_एमएस] INTO ##SQLskillsStats2FROM sys.dm_os_wait_stats;GO /* डिफ द वेट्स */ WITH एएस के साथ (चुनें --s डिफ द वेट्स */ सी) 't पहले स्नैपशॉट में [ts2]। [##SQLskillsStats1] AS [ts1] ऑन [ts2]।[wait_type] =[ts1]।[wait_type] जहां [ts1]।[wait_type] IS NULL और [ts2] है। दोनों स्नैपशॉट में प्रतीक्षा की टीएस [ts2]। [प्रतीक्षा_प्रकार], [ts2]। [प्रतीक्षा_समय_एमएस] - [ts1]। ts2]। [प्रतीक्षा_कार्य_गणना] - [ts1]। ts1]। [प्रतीक्षा_प्रकार] जहां [ts1]। [प्रतीक्षा_प्रकार] शून्य नहीं है और [ts2]। [प्रतीक्षा_कार्य_गणना] - [ts1]। ]> 0), [प्रतीक्षा करता है] एएस (चुनें [प्रतीक्षा_प्रकार], [प्रतीक्षा_समय_एमएस] / 1000.0 एएस [प्रतीक्षा करें], ([प्रतीक्षा_समय_एमएस] - [सिग्नल_वेट_टाइम_एमएस]) / 1000.0 एएस [संसाधन], [सिग्नल_वेट_टाइम_एमएस] / 1000.0 एएस [सिग्नल] , [वेटिंग_टास्क_काउंट] एएस [वेटकाउंट], 100.0 * [वेट_टाइम_एमएस] / एसयूएम ([वेट_टाइम_एमएस]) ओवर () एएस [प्रतिशत], ROW_NUMBER () ओवर (ऑर्डर बाय [वेट_टाइम_एमएस] डीईएससी) एएस [रोनम] से [डिफवेट्स] जहां से [प्रतीक्षा_प्रकार] में नहीं (से प्रतीक्षा प्रकार चुनें SQLskills_WaitStats.dbo.WaitsToIgnore)) INSERT INTO [बेसलाइनडेटा]। AvgRes_S] , [AvgSig_S])चुनें [W1]।[wait_type], CAST ([W1]।[WaitS] AS DECIMAL (16, 2)), CAST ([W1]। [ResourceS] AS DECIMAL (16, 2) ), कास्ट ([W1]। [सिग्नल] दशमलव के रूप में (16, 2)), [W1]। [प्रतीक्षा गणना], कास्ट ([W1]। [प्रतिशत] दशमलव के रूप में (5, 2)), कास्ट (([ W1]। [प्रतीक्षा करें] / [डब्ल्यू 1]। [प्रतीक्षा गणना]) दशमलव के रूप में (16, 4)), कास्ट (([डब्ल्यू 1]। [संसाधन] / [डब्ल्यू 1]। [प्रतीक्षा गणना]) दशमलव के रूप में (16, 4) ), कास्ट (([W1]। [सिग्नल] / [W1]। [वेटकाउंट]) दशमलव के रूप में (16, 4)) से [वेट्स] AS [W1]INNER जॉइन [वेट्स] AS [W2]ON [W2] [RowNum] <=[W1]। [RowNum] ग्रुप बाय [W1]।[RowNum], [W1]। [सिग्नल], [डब्ल्यू1]। [प्रतीक्षागणना], [डब्ल्यू1]। -- प्रतिशत थ्रेशोल्डGO /* अस्थायी तालिकाओं को साफ़ करें */ IF EXISTS (चुनें * [tempdb] से। [sys]। [ऑब्जेक्ट्स] जहां [नाम] =N'##SQLskillsStats1') ड्रॉप टेबल [##SQLskillsStats1]; IF EXISTS (चुनें * [tempdb] से। [sys]। [ऑब्जेक्ट्स] जहां [name] =N'##SQLskillsStats2') ड्रॉप टेबल [##SQLskillsStats2];

क्या मेरा नया तरीका बेहतर है? मुझे ऐसा लगता है, क्योंकि यह इस बात का बेहतर प्रतिनिधित्व है कि कैप्चर के समय वेट कैसा दिखता है, और यह अभी भी एक नियमित अंतराल पर नमूना ले रहा है। दोनों विधियों के लिए, मैं आमतौर पर यह देखने के लिए देखता हूं कि कैप्चर के समय सबसे अधिक प्रतीक्षा क्या थी:

चुनें [w]।[कैप्चरडेट] , [w]। ]से   [डीबीओ]। m ON [w]।[RowNum] =[m]।[RowNumber]ORDER by [w]। 

परिणाम:

प्रत्येक स्नैपशॉट के लिए शीर्ष प्रतीक्षा (नमूना आउटपुट)

मेरी मूल स्क्रिप्ट में जो कमी थी, वह यह है कि यह अभी भी सिर्फ एक स्नैपशॉट है . मैं समय के साथ उच्चतम प्रतीक्षा कर सकता हूं, लेकिन अगर स्नैपशॉट के बीच कोई समस्या होती है, तो वह दिखाई नहीं देगी। तो आप क्या कर सकते हैं?

आप अपने कैप्चर की आवृत्ति बढ़ा सकते हैं। शायद हर घंटे प्रतीक्षा आंकड़ों को कैप्चर करने के बजाय, आप उन्हें हर 15 मिनट में कैप्चर करते हैं। या शायद हर 10. जितनी बार आप डेटा को कैप्चर करते हैं, उतनी ही बेहतर संभावना है कि आपके पास एक प्रदर्शन समस्या को फंसाने का मौका होगा।

आपका दूसरा विकल्प तीसरे पक्ष के एप्लिकेशन का उपयोग करना होगा, जैसे SQL संतरी प्रदर्शन सलाहकार, प्रतीक्षा की निगरानी के लिए। प्रदर्शन सलाहकार ठीक उसी जानकारी को sys.dm_os_wait_stats DMV से खींचता है। यह हर 10 सेकंड में sys.dm_os_wait_stats को एक बहुत ही सरल क्वेरी के साथ क्वेरी करता है:

चुनें * sys.dm_os_wait_stats से जहां wait_time_ms> 0;

परदे के पीछे, प्रदर्शन सलाहकार फिर इस डेटा को लेता है और इसे अपने निगरानी डेटाबेस में जोड़ता है। जब आप डेटा देखते हैं, तो सौम्य प्रतीक्षा हटा दी जाती है, और आपके लिए डेल्टा की गणना की जाती है। इसके अलावा, प्रदर्शन सलाहकार के पास एक शानदार प्रदर्शन है (डैशबोर्ड को देखना ऊपर दिए गए टेक्स्ट आउटपुट की तुलना में बहुत अच्छा है) और यदि आप चाहें तो संग्रह को अनुकूलित कर सकते हैं। यदि हम प्रदर्शन सलाहकार को देखते हैं और पूरे दिन के डेटा को देखते हैं, तो मैं आसानी से देख सकता हूँ कि SQL सर्वर प्रतीक्षा फलक में मुझे कहाँ कोई समस्या थी:

दिन के लिए प्रदर्शन सलाहकार डैशबोर्ड

और जो कुछ हुआ उसकी आगे जांच करने के लिए मैं दोपहर 3 बजे के बाद उस समयावधि में ड्रिल कर सकता हूं:

प्रदर्शन समस्या के दौरान PA में ड्रिल डाउन करें

अपने आप निगरानी करना, जब तक कि मैं एक स्क्रिप्ट के साथ एक ही समय में स्नैपशॉट प्रतीक्षा आंकड़ों के साथ नहीं हुआ, मैं उस प्रदर्शन समस्या के बारे में किसी भी डेटा को कैप्चर करने से चूक जाऊंगा। क्योंकि प्रदर्शन सलाहकार एक विस्तारित अवधि के लिए जानकारी संग्रहीत करता है, यदि आपके प्रदर्शन में कोई कमी है, तो आप करते हैं समस्या पर शोध करने में सहायता के लिए प्रतीक्षा आँकड़े डेटा (बहुत सी अन्य जानकारी के साथ) उपलब्ध है, और आपके पास ऐतिहासिक डेटा भी है ताकि आप समझ सकें कि आपके परिवेश में सामान्य प्रतीक्षा क्या मौजूद है।

सारांश

मॉनिटर करने के लिए आप जो भी तरीका चुनते हैं, वे इंतजार करते हैं, सबसे पहले यह समझना जरूरी है कि कैसे SQL सर्वर प्रतीक्षा जानकारी संग्रहीत करता है, ताकि यदि आप इसे नियमित रूप से कैप्चर करते हैं तो आप जो डेटा देख रहे हैं उसे आप समझ सकते हैं। यदि आपको प्रतीक्षा को पकड़ने के लिए अपनी स्वयं की स्क्रिप्ट को रोल करना है, तो आप इसमें सीमित हैं कि आप विचलन को उतनी आसानी से नहीं पकड़ सकते जितना आप तृतीय पक्ष सॉफ़्टवेयर के साथ कर सकते हैं। लेकिन यह ठीक है - कुछ मात्रा में आधारभूत डेटा होने से आप यह समझना शुरू कर सकते हैं कि "सामान्य" क्या है कुछ भी न होने से बेहतर है . जैसे ही आप अपना भंडार बनाते हैं और पर्यावरण से परिचित होना शुरू करते हैं, आप किसी भी समस्या को हल करने के लिए अपनी कैप्चर स्क्रिप्ट को आवश्यकतानुसार तैयार कर सकते हैं। यदि आपको तृतीय पक्ष सॉफ़्टवेयर का लाभ मिलता है, तो उस जानकारी का पूरा उपयोग करें, और सुनिश्चित करें कि आप समझते हैं कि प्रतीक्षा कैसे एकत्र और संग्रहीत की जा रही है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर ब्लॉकिंग के साथ DBA डोर पर ब्लॉक, ब्लॉक, ब्लॉकिंग

  2. क्या मैं प्राथमिक कुंजी के लिए अनदेखा_dup_key चालू कर सकता हूं?

  3. SQL सर्वर में सर्वर जानकारी प्राप्त करने के लिए SERVERPROPERTY () का उपयोग करें

  4. एकल कॉलम मानों को एकाधिक कॉलम मानों में कैसे विभाजित करें?

  5. SQL सर्वर का उपयोग करके रिवर्स ऑर्डर में स्ट्रिंग कैसे लौटाएं - रिवर्स ()