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

विभिन्न कर्सर विकल्पों का क्या प्रभाव हो सकता है?

मैंने कर्सर का उपयोग करने के बारे में कई बार लिखा है और कैसे, ज्यादातर मामलों में, सेट-आधारित तर्क का उपयोग करके अपने कर्सर को फिर से लिखना अधिक कुशल है।

हालांकि, मैं यथार्थवादी हूं।

मुझे पता है कि ऐसे मामले हैं जहां कर्सर "आवश्यक" हैं - आपको किसी अन्य संग्रहीत प्रक्रिया को कॉल करने या प्रत्येक पंक्ति के लिए एक ई-मेल भेजने की आवश्यकता है, आप प्रत्येक डेटाबेस के विरुद्ध रखरखाव कार्य कर रहे हैं, या आप एक बार का कार्य चला रहे हैं जो बस सेट-आधारित में बदलने के लिए समय निवेश करने लायक नहीं है।

आप (शायद) इसे आज कैसे कर रहे हैं

भले ही आप अभी भी कर्सर का उपयोग कर रहे हों, आपको कम से कम सावधान रहना चाहिए कि काफी महंगे डिफ़ॉल्ट विकल्पों का उपयोग न करें। ज्यादातर लोग अपने कर्सर को इस तरह से शुरू करते हैं:

DECLARE c CURSOR FOR 
  SELECT whatever FROM ...

अब फिर, तदर्थ, एकबारगी कार्यों के लिए, यह शायद ठीक है। लेकिन वहाँ हैं…

इसे करने के अन्य तरीके

मैं डिफ़ॉल्ट का उपयोग करके कुछ परीक्षण चलाना चाहता था और उनकी तुलना विभिन्न कर्सर विकल्पों जैसे LOCAL से करना चाहता था , स्थिर , READ_ONLY और FAST_FORWARD . (विकल्पों में से एक टन हैं, लेकिन ये सबसे अधिक उपयोग किए जाने वाले हैं क्योंकि वे सबसे सामान्य प्रकार के कर्सर संचालन पर लागू होते हैं जिनका लोग उपयोग करते हैं।) न केवल मैं कुछ अलग संयोजनों की कच्ची गति का परीक्षण करना चाहता था, बल्कि शीत सेवा के पुनरारंभ होने और गर्म कैश के साथ, दोनों tempdb और स्मृति पर भी प्रभाव।

जिस क्वेरी को मैंने कर्सर को फीड करने का निर्णय लिया वह sys.objects . के विरुद्ध एक बहुत ही सरल क्वेरी है , AdventureWorks2012 नमूना डेटाबेस में। यह मेरे सिस्टम पर 318,500 पंक्तियाँ देता है (4GB RAM वाला एक बहुत ही विनम्र 2-कोर सिस्टम):

SELECT c1.[object_id] 
  FROM sys.objects AS c1
  CROSS JOIN (SELECT TOP 500 name FROM sys.objects) AS c2;

फिर मैंने इस क्वेरी को विभिन्न विकल्पों (डिफ़ॉल्ट सहित) के साथ एक कर्सर में लपेटा और कुछ परीक्षण चलाए, कुल सर्वर मेमोरी को मापने के लिए, टेम्पर्ड को आवंटित पृष्ठ (sys.dm_db_task_space_usage के अनुसार) और/या sys.dm_db_session_space_usage ), और कुल अवधि। मैंने ग्लेन बेरी और रॉबर्ट डेविस की लिपियों का उपयोग करके tempdb विवाद का निरीक्षण करने का भी प्रयास किया, लेकिन मेरी कमजोर प्रणाली पर मैं किसी भी विवाद का पता नहीं लगा सका। निश्चित रूप से मैं भी एसएसडी पर हूं और सिस्टम पर कुछ और नहीं चल रहा है, इसलिए ये ऐसी चीजें हो सकती हैं जिन्हें आप अपने स्वयं के परीक्षणों में जोड़ना चाहते हैं यदि tempdb एक बाधा होने की अधिक संभावना है।

तो अंत में प्रश्न कुछ इस तरह दिखे, निदान संबंधी प्रश्नों को उपयुक्त बिंदुओं पर शामिल किया गया:

DECLARE @i INT = 1;
 
DECLARE c CURSOR
-- LOCAL
-- LOCAL STATIC
-- LOCAL FAST_FORWARD
-- LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
  SELECT c1.[object_id] 
    FROM sys.objects AS c1
    CROSS JOIN (SELECT TOP 500 name FROM sys.objects) AS c2
    ORDER BY c1.[object_id];
 
OPEN c;
FETCH c INTO @i;
 
WHILE (@@FETCH_STATUS = 0)
BEGIN
  SET @i += 1; -- meaningless operation
  FETCH c INTO @i;
END
 
CLOSE c;
DEALLOCATE c;

परिणाम

    अवधि

    यकीनन सबसे महत्वपूर्ण और सामान्य उपाय है, "इसमें कितना समय लगा?" खैर, डिफ़ॉल्ट विकल्पों (या केवल LOCAL के साथ) के साथ कर्सर चलाने में लगभग पांच गुना समय लगा निर्दिष्ट), या तो निर्दिष्ट करने की तुलना में STATIC या FAST_FORWARD :

    स्मृति

    मैं अतिरिक्त मेमोरी को भी मापना चाहता था जो SQL सर्वर प्रत्येक कर्सर प्रकार को पूरा करते समय अनुरोध करेगा। इसलिए मैंने प्रदर्शन काउंटर कुल सर्वर मेमोरी (KB) को मापते हुए, प्रत्येक कोल्ड कैश परीक्षण से पहले बस पुनः आरंभ किया। प्रत्येक परीक्षण से पहले और बाद में। यहां सबसे अच्छा संयोजन था LOCAL FAST_FORWARD :

    tempdb उपयोग

    यह परिणाम मेरे लिए आश्चर्यजनक था। चूंकि एक स्थिर कर्सर की परिभाषा का अर्थ है कि यह पूरे परिणाम को tempdb पर कॉपी करता है, और यह वास्तव में sys.dm_exec_cursors में व्यक्त किया जाता है। स्नैपशॉट . के रूप में , मुझे उम्मीद थी कि tempdb पृष्ठों पर हिट कर्सर के सभी स्थिर रूपों के साथ अधिक होगी। यह मामला नहीं था; फिर से हम डिफ़ॉल्ट कर्सर और केवल LOCAL के साथ tempdb उपयोग पर लगभग 5X हिट देखते हैं निर्दिष्ट:

निष्कर्ष

वर्षों से मैं इस बात पर जोर दे रहा हूं कि निम्नलिखित विकल्प हमेशा आपके कर्सर के लिए निर्दिष्ट किए जाने चाहिए:

LOCAL STATIC READ_ONLY FORWARD_ONLY

इस बिंदु से, जब तक मुझे आगे के क्रमपरिवर्तन का परीक्षण करने का मौका नहीं मिलता है या किसी भी मामले को खोजने का मौका नहीं मिलता है, जहां यह सबसे तेज़ विकल्प नहीं है, मैं निम्नलिखित की सिफारिश करूंगा:

LOCAL FAST_FORWARD

(एक तरफ के रूप में, मैंने LOCAL . को छोड़कर परीक्षण भी चलाए विकल्प, और अंतर नगण्य थे।)

उस ने कहा, यह जरूरी नहीं कि *सभी* कर्सर के लिए सही हो। इस मामले में, मैं केवल कर्सर के बारे में बात कर रहा हूं जहां आप केवल आगे की दिशा में कर्सर से डेटा पढ़ रहे हैं, और आप अंतर्निहित डेटा को अपडेट नहीं कर रहे हैं (या तो कुंजी द्वारा या WHERE CURRENT OF<का उपयोग करके) /कोड> ) वे एक और दिन के लिए परीक्षण हैं।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. प्रदर्शन आश्चर्य और अनुमान:GROUP BY बनाम DISTINCT

  2. डेटाबेस डिजाइनर क्या करता है?

  3. RMAN कमांड ORA-00904:"BS" के साथ विफल हो जाते हैं।" GUID":अमान्य पहचानकर्ता

  4. SQL क्वेरी को कैसे गति दें

  5. PRAGMA EXCEPTION_INIT का उपयोग करके उपयोगकर्ता परिभाषित अपवाद को कैसे घोषित करें?