2011-08-09 13 views
6

का उपयोग करते समय बहुत धीमी सबक्वायरीज़ मैं बड़े प्री-मौजूदा एक्सेस डेटाबेस (~ 500 एमबी कॉम्पैक्ट & मरम्मत के बाद ~ 500 एमबी के भीतर निहित डेटा के लिए रिपोर्ट जेनरेट करने पर काम कर रहा हूं), और मुझे धीमी सबक्वायरी में समस्या हो रही है ।"नहीं IN"

डेटाबेस में एक बड़ी तालिका है जिसमें प्रत्येक ग्राहक खरीद का रिकॉर्ड होता है। यहां एक साधारण क्वेरी है जो ग्राहकों को नीली विजेट खरीदी है। यह कुछ सेकंड के भीतर पूरा हो जाता है और लगभग दस हजार रिकॉर्ड देता है।

SELECT DISTINCT CustomerId 
FROM ProductSales 
WHERE Product = 'BLUE' 

यहाँ एक प्रश्न ग्राहकों को जो एक नीले विजेट खरीदा है खोजने की कोशिश करता है जो, लेकिन नहीं एक लाल विजेट है। इसे चलाने में लगभग एक घंटे लगते हैं।

SELECT DISTINCT CustomerId FROM ProductSales 
WHERE Product = 'BLUE' 
AND CustomerId NOT IN (
    SELECT CustomerId 
    FROM ProductSales 
    WHERE Product = 'RED' 
) 

क्या दूसरी क्वेरी को दोबारा करने में कुछ मिनट लगने का कोई तरीका है?

+0

मुझे लगता है कि ग्राहक आईडी फ़ील्ड में दोनों टेबलों पर इंडेक्स हैं? –

+0

क्या आपने उत्पादसेल्स से चयनित डिस्टिंट ग्राहक आईडी का चयन किया है, जहां उत्पाद = 'नीला' शून्य उत्पाद उत्पाद से उत्पाद चुनें जहां उत्पाद = 'लाल' है। मैंने उन मामलों को देखा है जहां यह वास्तव में क्वेरी को तेज करता है, लेकिन वाईएमएमवी –

+0

@ मार्क बी: यहां केवल एक तालिका है, लेकिन ग्राहक आईडी को इस पर अनुक्रमित किया गया है। – James

उत्तर

10

पहुँच 'डेटाबेस इंजन, Not In के लिए एक सूचकांक का उपयोग नहीं कर सकते हैं तो यह धीमी गति से होने के लिए बाध्य है। ग्राहक आईडी पर एक इंडेक्स के साथ, यह क्वेरी बहुत तेज होनी चाहिए क्योंकि डीबी इंजन इंडेक्स का उपयोग कर सकता है।

SELECT DISTINCT blue.CustomerId 
FROM 
    ProductSales AS blue 
    LEFT JOIN 
     (
      SELECT CustomerId 
      FROM ProductSales 
      WHERE Product = 'RED' 
     ) AS red 
    ON blue.CustomerId = red.CustomerId 
WHERE 
     blue.Product = 'BLUE' 
    AND red.CustomerId Is Null; 

आप शायद यह भी एक Not Exists दृष्टिकोण की कोशिश कर सकते हैं, लेकिन सूचकांक उपयोग वहाँ इसकी गारंटी नहीं है। इसके अलावा, कृपया डेविड फेंटन से नीचे दी गई टिप्पणी देखें जो अधिक प्रभाव में प्रदर्शन प्रभाव पर चर्चा करती है।

+1

वाह। 60 मिनट से एक सेकंड तक नीचे। यह पुराने संस्करण की तुलना में 3600 गुना तेज है। धन्यवाद! :-) भविष्य के संदर्भ के लिए, क्या एसक्यूएल ऑपरेशंस की एक सूची है कहीं भी इंडेक्स का उपयोग नहीं करता है? – James

+1

शायद कहीं एक सूची है, लेकिन मुझे नहीं पता कि कहां है। :-) यदि आप इस पर कट्टर जाना चाहते हैं, तो Google Jet ShowPlan ... जो आपको अधिकृत रूप से बताएगा कि कैसे/डीबी इंजन आपकी क्वेरी के साथ इंडेक्स का उपयोग कर रहा है। आप क्वेरी प्रदर्शन के बारे में विस्तृत चर्चा यहां देख सकते हैं: http://msdn.microsoft.com/en-us/library/aa188211(office.10).aspx – HansUp

+1

ऐसा नहीं है कि EXISTS इंडेक्स का उपयोग कभी नहीं करते - यह है कि आप भविष्यवाणी नहीं कर सकते कि वे कब करेंगे और कब नहीं करेंगे। किसी भी समय जब आप जॉइन में एक इन/एक्सस्टिक्स सबक्वायरी को फिर से इंजीनियर नहीं कर सकते हैं, तो आप प्रदर्शन में सुधार करेंगे। हालांकि, यह सब परिणामी रिकॉर्डसेट की संपादन क्षमता पर निर्भर करता है - जॉइन में उपयोग की जाने वाली कुछ सबक्विरी क्वेरी को गैर-अद्यतन करने योग्य बनाती हैं। –

0

यदि आपके पास कोई नहीं है, तो निश्चित रूप से एक अनुक्रमणिका जोड़ें। यदि यह एक समस्या है, तो शायद यह है कि बहुत सारे ग्राहक लाल के अलावा कुछ और के लिए ऑर्डर के साथ हैं लेकिन ब्लू के साथ बहुत सारे नहीं हैं; यह (अवांछित) क्वेरी इसे ठीक करने का प्रयास करती है।

SELECT DISTINCT CustomerId FROM ProductSales 
LEFT JOIN (
    SELECT DISTINCT CustomerId cid FROM ProductSales 
    LEFT JOIN (
    SELECT DISTINCT CustomerId 
    FROM ProductSales 
    WHERE Product = 'BLUE' 
) foo ON CustomerId = cid 
    WHERE Product = 'RED' 
) bar USING (CustomerId) 
WHERE cid IS NULL 
संबंधित मुद्दे