IF EXISTS में रैपिंग क्वेरी इसे बहुत धीमा कर देती है


16

मेरे पास नीचे का प्रश्न है:

select databasename 
from somedb.dbo.bigtable l where databasename ='someval' and source  <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)

उपरोक्त क्वेरी तीन सेकंड में पूरी होती है।

यदि उपरोक्त क्वेरी कोई भी मान लौटाती है, तो हम EXIT में संग्रहीत कार्यविधि चाहते हैं, इसलिए मैं इसे नीचे की तरह फिर से लिखता हूं:

If Exists(
select databasename 
from somedb.dbo.bigtable l where databasename ='someval' and source  <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)
)
Begin
Raiserror('Source missing',16,1)
Return
End

हालांकि इसमें 10 मिनट का समय लग रहा है।

मैं नीचे की तरह उपरोक्त क्वेरी फिर से लिख सकता हूं, जो 3 सेकंड से भी कम समय में पूरी होती है:

  select databasename 
from somedb.dbo.bigtable l where databasename ='someval' and source  <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source
if @@rowcount >0
Begin
Raiserror('Source missing',16,1)
Return
End

उपरोक्त पुनर्लेखन के साथ मुद्दा यह है कि उपरोक्त क्वेरी बड़ी संग्रहित प्रक्रिया का हिस्सा है और यह कई परिणाम सेट लौटाता है। C # में, हम प्रत्येक परिणाम सेट के माध्यम से पुनरावृत्ति करते हैं और कुछ प्रसंस्करण करते हैं।

उपरोक्त एक रिक्त परिणाम सेट देता है, इसलिए यदि मैं इस दृष्टिकोण के साथ जाता हूं, तो मुझे अपना सी # बदलना होगा और फिर से तैनाती करनी होगी।

तो मेरा सवाल है,

सिर्फ IF EXISTSइतना समय लेने की योजना में बदलाव क्यों करता है ?

नीचे विवरण दिए गए हैं जो आपकी मदद कर सकते हैं और मुझे बताएं कि क्या आपको किसी विवरण की आवश्यकता है:

  1. मेरी जैसी योजना बनाने के लिए तालिका और सांख्यिकी स्क्रिप्ट बनाएं
  2. धीमी निष्पादन योजना
  3. तेज निष्पादन योजना

    ब्रेंटोजर पेस्ट का उपयोग करके योजना को धीमा करें ब्रेंटोजर योजना का उपयोग करके
    फास्ट प्लान की योजना बनाएं

नोट: दोनों प्रश्न समान हैं (मापदंडों का उपयोग करते हुए), एकमात्र अंतर यह है EXISTS(हालांकि मैंने अज्ञात करते समय कुछ गलतियाँ की हैं)।

तालिका निर्माण स्क्रिप्ट नीचे हैं:

http://pastebin.com/CgSHeqXc - छोटी तालिका आँकड़े
http://pastebin.com/GUu9KfpS - बड़ी तालिका आँकड़े


इस प्रश्न पर चर्चा को इस चैट रूम में स्थानांतरित कर दिया गया है ।
पॉल व्हाइट को फिर से बहाल मोनिका

जवाबों:


18

द्वारा समझाया कर दिया गया है के रूप में पॉल व्हाइट : अपने ब्लॉग पोस्ट में अंदर अनुकूलक: पंक्ति लक्ष्य गहराई मेंEXISTS प्रस्तुत किया एक पंक्ति लक्ष्य है, जो पसंद करते हैं NESTED LOOPSया MERGE JOINअधिकHASH MATCH

अंतिम उदाहरण के रूप में, विचार करें कि एक तार्किक अर्ध-जुड़ाव (जैसे EXISTS के साथ पेश की गई एक उप-क्वेरी) समग्र विषय साझा करता है: इसे पहली मिलान पंक्ति को जल्दी से खोजने के लिए अनुकूलित किया जाना चाहिए।

आपकी क्वेरी में यह स्पष्ट रूप से नेस्टेड छोरों को पेश करने और समानता को हटाने के लिए होता है, जिसके परिणामस्वरूप एक धीमी योजना होती है।

इसलिए आपको शायद अपनी क्वेरी का उपयोग किए बिना अपनी क्वेरी को फिर से लिखने का एक तरीका खोजना होगा NOT EXISTS

आप अपनी क्वेरी को फिर से लिखने के साथ दूर हो सकते हैं LEFT OUTER JOINऔर परीक्षण के लिए परीक्षण करके छोटी सी पंक्ति में कोई पंक्ति नहीं थीNULL

If EXISTS(
    SELECT databasename
    FROM somedb.dbo.bigtable l
    LEFT JOIN dbo.smalltable c ON c.source = l.source
    WHERE databasename = 'someval'
    AND source <> 'kt'
    AND c.source IS NULL
)

आप शायद एक EXCEPTक्वेरी का भी उपयोग कर सकते हैं, इस पर निर्भर करता है कि आपको इस तरह की तुलना करने के लिए कितने क्षेत्रों की आवश्यकता है:

If EXISTS(
   SELECT source
   FROM somedb.dbo.bigtable l
   WHERE databasename = 'someval'
   AND source <> 'kt'

   EXCEPT

   SELECT source
   FROM dbo.smalltable
)

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

संबंधित प्रश्नोत्तर: यदि चयनित चयन विवरण से अधिक समय लग रहा है


0

आपको स्पष्ट क्वेरी का उपयोग करके अपनी क्वेरी को फिर से लिखना होगा और निर्दिष्ट करना होगा कि कौन सा ऑपरेशन आप इस तरह से उपयोग करना चाहते हैं (लूप, हैश या मर्ज)।

If not exists(
    select databasename 
    from somedb.dbo.bigtable l
    inner hash join dbo.smalltable c 
        on c.source = l.source
where databasename ='someval' and source  <>'kt')
begin
    Raiserror('Source missing',16,1)
    Return
end

EXISTS या NOT EXISTS का उपयोग करते समय NESTED LOOP ऑपरेशन के साथ SQL सर्वर जनरेट क्वेरी प्लान यह मानते हुए कि यह शर्त को पूरा करने के लिए पहली पंक्ति में एक-एक करके सभी पंक्तियों में जाना चाहिए। HASH JOIN के उपयोग से इसे गति मिलेगी।


आपकी तुलना में, इसका परीक्षण करेंगे
TheGameiswar

0

मैं एक ही मुद्दे पर आया हूं, मैंने "EXISTS" के उपयोग से बचने और "COUNT ()" फ़ंक्शन और "IF ... ELSE" कथन का उपयोग करके अपने आप को गोल करने का प्रबंधन किया।

अपने उदाहरण के लिए निम्नलिखित प्रयास करें:

IF
(
    SELECT
        COUNT(l.databasename) + 1 AS databasename
    FROM somedb.dbo.bigtable AS l

    WHERE   l.databasename ='someval'
        AND l.[source]  <> 'kt'
        AND NOT EXISTS(SELECT 1 FROM dbo.smalltable AS c WHERE c.[source]=l.[source])
) > 1 --Acts like EXISTS
BEGIN
    RAISERROR('Source missing', 16, 1)
RETURN
END

कारण मैं गिनती में "+ 1" जोड़ रहा हूं ताकि मैं "> 1" का उपयोग सही स्थिति में कर सकूं, "> 0" या "<> 0" का उपयोग करके क्वेरी को एचएएसएच के बजाय नेस्टेड छोरों का उपयोग करने के लिए ट्रिगर किया जाएगा। मिलान। ध्यान नहीं दिया कि ऐसा क्यों हो रहा है, यह जानना दिलचस्प होगा कि ऐसा क्यों हुआ।

उम्मीद है की वो मदद करदे!

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