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

सेवा शुरू करने के बाद पहली बार यह क्वेरी धीमी क्यों है?

मैं <स्ट्राइक>कर सकता हूं मेरी मशीन पर इस 100% समय को भी पुन:पेश कर सकता है। (नोट अंत में देखें)

समस्या का सार यह है कि आप S . निकाल रहे हैं tempdb . में सिस्टम तालिका पंक्तियों पर ताले जो आंतरिक tempdb . के लिए आवश्यक तालों के साथ विरोध कर सकता है सफाई लेनदेन।

जब यह सफाई कार्य उसी सत्र को आवंटित किया जाता है जिसके पास S . होता है लॉक अनिश्चितकालीन हैंग हो सकता है।

निश्चित रूप से इस समस्या से बचने के लिए आपको system . का संदर्भ देना बंद करना होगा tempdb . के अंदर की वस्तुएं ।

किसी भी बाहरी तालिका को संदर्भित किए बिना संख्या तालिका बनाना संभव है। निम्नलिखित को कोई आधार तालिका पंक्तियों को पढ़ने की आवश्यकता नहीं है और इस प्रकार कोई ताले भी नहीं लगते हैं।

WITH Ten(N) AS 
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)   
SELECT TOP 1000000 IDENTITY(INT, 1, 1) Number
INTO   Numbers
FROM   Ten T10,
       Ten T100,
       Ten T1000,
       Ten T10000,
       Ten T100000,
       Ten T1000000 

प्रजनन के चरण

पहले एक प्रक्रिया बनाएं

CREATE PROC P
AS
    SET NOCOUNT ON;

    DECLARE @T TABLE (X INT)
GO

फिर SQL सेवा को पुनरारंभ करें और एक कनेक्शन में निष्पादित करें

WHILE NOT EXISTS(SELECT *
                 FROM   sys.dm_os_waiting_tasks
                 WHERE  session_id = blocking_session_id)
  BEGIN

      /*This will cause the problematic droptemp transactions*/
      EXEC sp_recompile 'P'

      EXEC P
  END;

SELECT *
FROM   sys.dm_os_waiting_tasks
WHERE  session_id = blocking_session_id 

फिर दूसरे कनेक्शन में चलाएं

USE tempdb;

SELECT TOP 1000000 IDENTITY(INT, 1, 1) Number
INTO #T
FROM sys.objects s1
CROSS JOIN sys.objects s2
CROSS JOIN sys.objects s3
CROSS JOIN sys.objects s4;

DROP TABLE #T

संख्या तालिका को पॉप्युलेट करने वाली क्वेरी आंतरिक सिस्टम लेनदेन के साथ लाइव लॉक स्थिति में आने का प्रबंधन करती है जो अस्थायी वस्तुओं जैसे तालिका चर को साफ करती है।

मैं सत्र आईडी 53 को इस तरह से अवरुद्ध करने में कामयाब रहा। यह अनिश्चित काल के लिए अवरुद्ध है। sp_WhoIsActive . का आउटपुट दिखाता है कि यह मकड़ी लगभग सारा समय निलंबित रहने में बिताती है। लगातार रन में reads . में नंबर कॉलम बढ़ता है लेकिन अन्य कॉलम में मान काफी हद तक वही रहता है।

प्रतीक्षा अवधि बढ़ते हुए पैटर्न को नहीं दिखाती है, हालांकि यह इंगित करती है कि इसे फिर से अवरुद्ध होने से पहले समय-समय पर अनब्लॉक किया जाना चाहिए।

SELECT *
FROM   sys.dm_os_waiting_tasks
WHERE  session_id = blocking_session_id

रिटर्न

+----------------------+------------+-----------------+------------------+-----------+--------------------+-----------------------+---------------------+--------------------------+--------------------------------------------------------------------------------------------------+
| waiting_task_address | session_id | exec_context_id | wait_duration_ms | wait_type |  resource_address  | blocking_task_address | blocking_session_id | blocking_exec_context_id |                                       resource_description                                       |
+----------------------+------------+-----------------+------------------+-----------+--------------------+-----------------------+---------------------+--------------------------+--------------------------------------------------------------------------------------------------+
| 0x00000002F2C170C8   |         53 |               0 |               86 | LCK_M_X   | 0x00000002F9B13040 | 0x00000002F2C170C8    |                  53 | NULL                     | keylock hobtid=281474978938880 dbid=2 id=lock2f9ac8880 mode=U associatedObjectId=281474978938880 |
+----------------------+------------+-----------------+------------------+-----------+--------------------+-----------------------+---------------------+--------------------------+--------------------------------------------------------------------------------------------------+

संसाधन विवरण में आईडी का उपयोग करना

SELECT o.name
FROM   sys.allocation_units au WITH (NOLOCK)
       INNER JOIN sys.partitions p WITH (NOLOCK)
         ON au.container_id = p.partition_id
       INNER JOIN sys.all_objects o WITH (NOLOCK)
         ON o.object_id = p.object_id
WHERE  allocation_unit_id = 281474978938880 

रिटर्न

+------------+
|    name    |
+------------+
| sysschobjs |
+------------+

चल रहा है

SELECT resource_description,request_status
FROM   sys.dm_tran_locks 
WHERE request_session_id = 53 AND request_status <> 'GRANT'

रिटर्न

+----------------------+----------------+
| resource_description | request_status |
+----------------------+----------------+
| (246708db8c1f)       | CONVERT        |
+----------------------+----------------+

डीएसी के माध्यम से कनेक्ट हो रहा है और चल रहा है

SELECT id,name
FROM   tempdb.sys.sysschobjs WITH (NOLOCK)
WHERE %%LOCKRES%% = '(246708db8c1f)' 

रिटर्न

+-------------+-----------+
|     id      |   name    |
+-------------+-----------+
| -1578606288 | #A1E86130 |
+-------------+-----------+

उत्सुक है कि वह क्या है

SELECT name,user_type_id
FROM tempdb.sys.columns
WHERE object_id = -1578606288 

रिटर्न

+------+--------------+
| name | user_type_id |
+------+--------------+
| X    |           56 |
+------+--------------+

संग्रहित खरीद द्वारा उपयोग किए जाने वाले तालिका चर में यह स्तंभ नाम है।

चल रहा है

SELECT request_mode,
       request_status,
       request_session_id,
       request_owner_id,
       lock_owner_address,
       t.transaction_id,
       t.name,
       t.transaction_begin_time
FROM   sys.dm_tran_locks l
       JOIN sys.dm_tran_active_transactions t
         ON l.request_owner_id = t.transaction_id
WHERE  resource_description = '(246708db8c1f)' 

रिटर्न

+--------------+----------------+--------------------+------------------+--------------------+----------------+-------------+-------------------------+
| request_mode | request_status | request_session_id | request_owner_id | lock_owner_address | transaction_id |    name     | transaction_begin_time  |
+--------------+----------------+--------------------+------------------+--------------------+----------------+-------------+-------------------------+
| U            | GRANT          |                 53 |           227647 | 0x00000002F1EF6800 |         227647 | droptemp    | 2013-11-24 18:36:28.267 |
| S            | GRANT          |                 53 |           191790 | 0x00000002F9B16380 |         191790 | SELECT INTO | 2013-11-24 18:21:30.083 |
| X            | CONVERT        |                 53 |           227647 | 0x00000002F9B12FC0 |         227647 | droptemp    | 2013-11-24 18:36:28.267 |
+--------------+----------------+--------------------+------------------+--------------------+----------------+-------------+-------------------------+

तो SELECT INTO लेन-देन एक S holding धारण कर रहा है tempdb.sys.sysschobjs . में पंक्ति को लॉक करें तालिका चर से संबंधित #A1E86130 . droptemp लेन-देन को X नहीं मिल सकता है इस परस्पर विरोधी S . के कारण इस पंक्ति को लॉक करें ताला।

इस क्वेरी को बार-बार चलाने से पता चलता है कि transaction_id droptemp . के लिए लेन-देन बार-बार बदलता है।

मैं अनुमान लगाता हूं कि SQL सर्वर को इन आंतरिक लेनदेन को उपयोगकर्ता के स्पिड्स पर आवंटित करना चाहिए और उपयोगकर्ता के काम करने से पहले उन्हें प्राथमिकता देनी चाहिए। तो सत्र आईडी 53 एक स्थिर चक्र में फंस गया है जहां यह एक droptemp . शुरू करता है लेन-देन, उसी स्पिड पर चल रहे उपयोगकर्ता लेनदेन द्वारा अवरुद्ध है। आंतरिक लेन-देन को वापस ले लेता है और फिर प्रक्रिया को अनिश्चित काल तक दोहराता है।

यह स्पिड के हैंग होने के बाद SQL सर्वर प्रोफाइलर में विभिन्न लॉकिंग और ट्रांजेक्शन इवेंट्स को ट्रेस करके वहन किया जाता है।

मैंने उससे पहले की लॉकिंग घटनाओं का भी पता लगाया।

इवेंट ब्लॉक करना लॉक करें

अधिकांश साझा किए गए कुंजी लॉक SELECT INTO . द्वारा निकाले गए sysschobjs . में कुंजियों पर लेन-देन तुरंत रिहा हो जाओ। अपवाद (246708db8c1f) . पर पहला लॉक है ।

यह कुछ समझ में आता है क्योंकि योजना [sys].[sysschobjs].[clst] [o] के नेस्टेड लूप स्कैन दिखाती है। और क्योंकि अस्थायी वस्तुओं को नकारात्मक ऑब्जेक्ट दिया जाता है, वे स्कैन क्रम में सामने आने वाली पहली पंक्तियाँ होंगी।

मुझे ओपी में वर्णित स्थिति का भी सामना करना पड़ा जहां पहले तीन तरह से क्रॉस जॉइन चलाना चार तरह से एक को सफल होने की अनुमति देता है।

SELECT INTO . के लिए ट्रेस में पहली कुछ घटनाएं लेन-देन एक पूरी तरह से अलग पैटर्न हैं।

यह सेवा के पुनरारंभ होने के बाद था, इसलिए टेक्स्ट डेटा कॉलम में लॉक संसाधन मान सीधे तुलनीय नहीं हैं।

ऐसा लगता है कि पहली कुंजी पर ताला बनाए रखने के बजाय और बाद की चाबियों को प्राप्त करने और जारी करने का एक पैटर्न शुरू में उन्हें जारी किए बिना बहुत अधिक ताले प्राप्त कर लेता है।

मुझे लगता है कि निष्पादन रणनीति में कुछ भिन्नता होनी चाहिए जो इस मुद्दे से बचाती है।

अपडेट करें

कनेक्ट आइटम जो मैंने उठाया इस बारे में निश्चित के रूप में चिह्नित नहीं किया गया है, लेकिन मैं अब SQL सर्वर 2012 SP2 पर हूं और अब स्थायी के बजाय केवल अस्थायी स्वयं अवरोधन को पुन:उत्पन्न कर सकता हूं। मुझे अभी भी सेल्फ ब्लॉकिंग मिलती है लेकिन droptemp . को निष्पादित करने के कुछ असफल प्रयासों के बाद भी लेनदेन सफलतापूर्वक ऐसा प्रतीत होता है कि उपयोगकर्ता लेनदेन को संसाधित करने के लिए वापस जाना प्रतीत होता है। उसके बाद सिस्टम लेनदेन करता है फिर सफलतापूर्वक निष्पादित किया जाता है। अब भी उसी चक्कर में। (एक उदाहरण में आठ प्रयास चलते हैं। मुझे यकीन नहीं है कि यह लगातार दोहराया जाएगा)



  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 ​​सर्वर डिफ़ॉल्ट डेटाटाइम प्रारूप प्रदान करती हैं?

  2. प्रोग्राम के रूप में एसक्यूएल कोड जनरेट कर रहा है

  3. SQL सर्वर में TRY_CAST () कैसे काम करता है

  4. मैं SQL-सर्वर में एक उपयोगकर्ता कैसे बना सकता हूँ जिसके पास केवल एक तालिका तक पहुँच है, और केवल पंक्तियों को सम्मिलित कर सकता है

  5. विशेष वर्णों वाली CSV फ़ाइल बनाने के लिए Excel का उपयोग करना और फिर SSIS का उपयोग करके इसे db में आयात करना