एकल पंक्ति INSERT… अलग चयन की तुलना में बहुत धीमी का चयन करें


18

निम्नलिखित ढेर तालिका को देखते हुए 1 से 400 तक 400 पंक्तियों की संख्या:

DROP TABLE IF EXISTS dbo.N;
GO
SELECT 
    SV.number
INTO dbo.N 
FROM master.dbo.spt_values AS SV
WHERE 
    SV.[type] = N'P'
    AND SV.number BETWEEN 1 AND 400;

और निम्नलिखित सेटिंग्स:

SET NOCOUNT ON;
SET STATISTICS IO, TIME OFF;
SET STATISTICS XML OFF;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

निम्नलिखित SELECTकथन लगभग 6 सेकंड में पूरा होता है ( डेमो , प्लान ):

DECLARE @n integer = 400;

SELECT
    c = COUNT_BIG(*) 
FROM dbo.N AS N
CROSS JOIN dbo.N AS N2
CROSS JOIN dbo.N AS N3
WHERE 
    N.number <= @n
    AND N2.number <= @n
    AND N3.number <= @n
OPTION
    (OPTIMIZE FOR (@n = 1));

नोट: @ OPTIMIZE FORक्लॉज सिर्फ एक समझदारी से आकार के रिप्रो के उत्पादन के लिए है जो वास्तविक समस्या के आवश्यक विवरणों को कैप्चर करता है, जिसमें एक कार्डिनैलिटी मिसैस्टी भी शामिल है जो कई कारणों से उत्पन्न हो सकती है।

जब एकल-पंक्ति आउटपुट को तालिका में लिखा जाता है, तो 19 सेकंड लगते हैं ( डेमो , प्लान ):

DECLARE @T table (c bigint NOT NULL);

DECLARE @n integer = 400;

INSERT @T
    (c)
SELECT
    c = COUNT_BIG(*) 
FROM dbo.N AS N
CROSS JOIN dbo.N AS N2
CROSS JOIN dbo.N AS N3
WHERE 
    N.number <= @n
    AND N2.number <= @n
    AND N3.number <= @n
OPTION
    (OPTIMIZE FOR (@n = 1));

निष्पादन योजनाएं एक पंक्ति के सम्मिलित से अलग दिखाई देती हैं।

सभी अतिरिक्त समय सीपीयू के उपयोग से लगता है।

INSERTबयान इतना धीमा क्यों है ?

जवाबों:


21

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

कार्डिनैलिटी मिसस्टिमेशन जानबूझकर इस OPTIMIZE FORतरह से पेश किया जाता है कि हेप आशावादी की तुलना में कई गुना अधिक स्कैन किया जाता है, और यह स्पूल का परिचय नहीं देता है जैसा कि सामान्य रूप से होता है।

कारकों के इस संयोजन का मतलब है कि प्रदर्शन रनटाइम पर आवश्यक ताले की संख्या के प्रति बहुत संवेदनशील है।

SELECTएक अनुकूलन की अनुमति देता है कि बयान से लाभ पंक्ति-स्तरीय साझा ताले छोड़ी जाने वाली (केवल इरादे से साझा की पृष्ठ-स्तरीय ताले देखकर) जब वहाँ अप्रतिबद्ध डेटा पढ़ने का कोई खतरा नहीं है, और कोई ऑफ पंक्ति डेटा है।

INSERT...SELECTबयान, इस अनुकूलन से लाभ नहीं होता तो RID ताले के लाखों लिया जाता है और दूसरे मामले में प्रत्येक दूसरे जारी की है, इरादे से साझा की पृष्ठ-स्तरीय ताले के साथ।

अतिरिक्त सीपीयू और बीता समय के लिए लॉकिंग गतिविधि खातों की भारी मात्रा।

सबसे प्राकृतिक समाधान यह है कि ऑप्टिमाइज़र (और स्टोरेज इंजन) सुनिश्चित करने के लिए सभ्य कार्डिनैलिटी अनुमान प्राप्त करें ताकि वे अच्छे विकल्प बना सकें।

यदि यह वास्तविक उपयोग के मामले में व्यावहारिक नहीं है, INSERTऔर SELECTकथनों को SELECTएक चर में आयोजित किए जाने के परिणाम से अलग किया जा सकता है । यह SELECTकथन को लॉक-स्किपिंग ऑप्टिमाइज़ेशन से लाभान्वित करने की अनुमति देगा ।

अलगाव स्तर को बदलने के लिए भी काम किया जा सकता है, या तो साझा ताले नहीं लेने से, या यह सुनिश्चित करने से कि ताला वृद्धि जल्दी से जगह लेता है।

रुचि के अंतिम बिंदु के रूप में, क्वेरी को SELECTअनडूलेटेड ट्रेस ध्वज 8691 का उपयोग करके स्पूल के उपयोग को मजबूर करके अनुकूलित मामले की तुलना में भी तेज चलाने के लिए किया जा सकता है ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.