2010-05-12 20 views
7

मैं निम्नलिखित प्रश्न हैं:क्या यह सरल एसक्यूएल क्वेरी अनुकूलित किया जा सकता है?

SELECT COUNT(*) 
FROM Address adr INNER JOIN 
    Audit a on adr.UniqueId = a.UniqueId 
  • एक डेटाबेस पर (13 लाख पते, 4 मिलियन से अधिक आडिट)
  • दोनों UniqueId कॉलम प्राथमिक कुंजी

क्वेरी है समूह है पूरा करने में काफी समय लग रहा है। मुझे गूंगा लगता है, लेकिन क्या इसे अनुकूलित करने का कोई तरीका है? मैं उन सभी पता प्रविष्टियों को गिनना चाहता हूं जिनमें अंतर्निहित ऑडिटेबल है।

संपादित: अपने सभी आदानों की बहुत सराहना कर रहे हैं, यहाँ कुछ और जानकारी कर रहे हैं:

  • क्वेरी अक्सर (यह केवल मान्य है) नहीं चला जाएगा, लेकिन अनुक्रमित दृश्य टिप के लिए धन्यवाद, मैं निश्चित रूप से अपने ज्ञान में जोड़ दूंगा।
  • सभी पते में 1 से 1 ऑडिट संबंधित है। सभी ऑडिट पते नहीं हैं।
  • क्वेरी को समाप्त होने में 1 मिनट से अधिक समय लगता है। मुझे यह एक साधारण गिनती के लिए बहुत लंबा लगता है।
+0

आपके पास "लंबे समय" क्या है, क्या आपके पास क्वेरी के लिए निष्पादन योजना है? क्या आप टेबल के लिए स्कीमा प्रदान कर सकते हैं? यदि आप कहते हैं कि यह अच्छी तरह से अनुक्रमित है तो इसके लिए कोई भी समय लेने का कोई कारण नहीं है। –

+2

क्या आप क्वेरी प्लान के बारे में कोई जानकारी दे सकते हैं? (उदाहरण के लिए एसक्यूएल सर्वर मैनेजमेंट स्टूडियो या प्लान एक्सएमएल से एक स्क्रीनशॉट) इसके अलावा, पते के किस अनुपात में अंतर्निहित ऑडिटेबल है? –

+0

क्या आपने अनुक्रमित कॉलम में से किसी एक को चुनने का प्रयास किया है? पुराने दिनों में, यह COUNT (adr.uniqueid) कहने में तेज़ी से था क्योंकि यह इंडेक्स से आपको जो कुछ भी चाहिए उसे पढ़ सकता था और कभी भी टेबल पर नहीं जाना पड़ता था। मैं कोशिश करता हूँ। यह भी देखने के लिए जांचें कि तालिका के आंकड़े अद्यतित हैं या नहीं। – MJB

उत्तर

11

चूंकि आपके पास डेटा के दो सेट हैं, उसी मूल्य से आदेश दिया गया है .. क्या आपने नेस्टेड लूप में शामिल होने के बजाय विलय में शामिल होने का प्रयास किया है?

SET STATISTICS IO ON 
SET STATISTICS TIME ON 

SELECT COUNT(*) 
FROM Address adr INNER JOIN 
    Auditable a on adr.UniqueId = a.UniqueId 
OPTION (LOOP JOIN) 

SELECT COUNT(*) 
FROM Address adr INNER JOIN 
    Auditable a on adr.UniqueId = a.UniqueId 
OPTION (MERGE JOIN) 

SELECT COUNT(*) 
FROM Address adr INNER JOIN 
    Auditable a on adr.UniqueId = a.UniqueId 
OPTION (HASH JOIN) 

संपादित करें:

ये स्पष्टीकरण वैचारिक कर रहे हैं। SQL सर्वर मेरे उदाहरणों की तुलना में अधिक परिष्कृत परिचालन कर रहा है। यह वैचारिक समझ, एसईटी सांख्यिकी आदेशों के समय और तार्किक आईओ के माप से मेल खाती है, और क्वेरी निष्पादन योजनाओं की परीक्षा - मेरी क्वेरी ऑप्टिमाइज़िंग तकनीक (चार साल से अधिक उम्र के) का आधार बनती है। यह आपकी सेवा कर सकता है साथ ही यह मेरे पास है।

सेटअप

  • ताश के पत्तों की 5 डेक प्राप्त करें।
  • 1 डेक लें और एक मूल डेटा सेट तैयार करें।
  • अन्य 4 डेक लें और बाल डेटा सेट का उत्पादन करें।
  • कार्ड मूल्य द्वारा निर्धारित प्रत्येक डेटा को ऑर्डर करें।
  • माता-पिता डेटा सेट में कार्ड की संख्या होने दें।
  • बच्चे डेटा सेट में कार्ड की संख्या होने दें।

NestedLoop

  • माता पिता डेटा सेट के ऊपर से एक कार्ड ले लो।
  • मिलान के पहले अवसर के लिए सेट किए गए बाल डेटा सेट के भीतर खोजें (बाइनरी खोज का उपयोग करें)।
  • गैर-मिलान मिलने तक पहले मैच से बाल डेटा सेट में आगे बढ़ें। अब आपको सभी मैच मिल गए हैं।
  • पैरेंट डेटा सेट में प्रत्येक कार्ड के लिए इसे दोहराएं।

नेस्टेड लूप एल्गोरिथ्म दोहराता माता पिता डेटा सेट, और उसके बाद बच्चे डेटा हर माता-पिता के लिए एक बार सेट खोज करता है, यह लागत बनाने: मीटर * लॉग (एन)

मर्ज

  • लें मूल डेटा सेट के शीर्ष से एक कार्ड।
  • बाल डेटा सेट के शीर्ष से एक कार्ड लें।
  • यदि कार्ड मिलते हैं, तो प्रत्येक डेक के शीर्ष से कार्ड खींचें जब तक प्रत्येक से एक गैर-मिलान नहीं मिलता है। माता-पिता और बाल मैचों के बीच प्रत्येक मिलान करने वाली जोड़ी बनाएं।
  • यदि कार्ड मेल नहीं खाते हैं, तो माता-पिता और बाल कार्ड के बीच छोटे खोजें, और उस डेटा सेट के शीर्ष से एक कार्ड लें।

विलय में शामिल होने के बाद एल्गोरिदम एक बार माता-पिता डेटा सेट को पुन: स्थापित करता है और बच्चे डेटा एक बार सेट करता है, इसे लागत बनाते हैं: m + n। यह आदेश दिया जा रहा डेटा पर निर्भर करता है। यदि आप अन-आदेशित डेटा पर विलय में शामिल होने के लिए कहते हैं, तो आपको ऑर्डरिंग ऑपरेशन होगा! इससे लागत (एम * लॉग (एम)) + (एन * लॉग (एन)) + एम + एन है। यहां तक ​​कि कुछ मामलों में नेस्टेड लूप से भी बेहतर हो सकता है।

हैश

  • एक कार्ड तालिका प्राप्त करें।
  • प्रत्येक कार्ड को मूल डेटा सेट से लें और उसे कार्ड टेबल पर रखें जहां आप इसे पा सकते हैं (कार्ड मूल्य के साथ कुछ भी करने की ज़रूरत नहीं है, केवल आपके लिए सुविधाजनक होना चाहिए)।
  • प्रत्येक कार्ड को बच्चे डेटा सेट से लें, कार्डबोर्ड टेबल पर अपने मिलान करने वाले माता-पिता का पता लगाएं और मिलान करने वाली जोड़ी का उत्पादन करें।

हैश एल्गोरिदम में शामिल होने के बाद माता-पिता डेटा सेट एक बार और बच्चे डेटा सेट एक बार फिर से सेट करता है, इसे लागत बनाते हैं: m + n। यह मूल डेटा सेट की संपूर्ण सामग्री को पकड़ने के लिए एक बड़ी पर्याप्त कार्ड तालिका रखने पर निर्भर करता है।

+0

का प्रदर्शन बढ़ावा देता है कमाल! शामिल हो जाना एक 100% प्रदर्शन बढ़ावा है, दो गुना तेजी से। बहुत बहुत धन्यवाद, मुझे पता नहीं था कि हम एक प्रश्न के साथ किस प्रकार का उपयोग करने के लिए निर्दिष्ट कर सकते हैं, मैं निश्चित रूप से इन पर और अधिक पढ़ूंगा। फिर से धन्यवाद, मुझे लगता है कि यह एक स्वीकार्य उत्तर है :) क्या आप थोड़ा और समझाते हैं कि मर्ज में शामिल क्यों इतना तेज़ है? – ibiza

+0

+1 अच्छा, मुझे इस बारे में पता नहीं था! इस समाधान को प्रदान करने के लिए धन्यवाद। मैंने इससे सीखा! @ibiza: इस टिप्पणी के लिए धन्यवाद जो विचार के आदेश देने के लिए प्रदर्शन को बढ़ावा देता है। –

+0

यह संदर्भ के आधार पर भी होना चाहिए ... मैं सोच रहा हूं कि किस प्रकार के मामले में प्रत्येक प्रकार का सबसे अच्छा विकल्प – ibiza

0

सुनिश्चित नहीं हैं कि अगर यह तेजी से होगा, लेकिन आप निम्नलिखित

SELECT COUNT(adr.UniqueID) FROM Address adr INNER JOIN Auditable a on adr.UniqueId = a.UniqueId 

यह आप एक ही गिनती देना चाहिए क्योंकि unqieieid अशक्त कभी नहीं होगा की कोशिश कर सकते।

1

ऑडिटेबल है। पता लगाने के लिए एक विदेशी कुंजी संदर्भ। यूनिकिड, जिसका अर्थ है ऑडिटेबल में कोई मूल्य नहीं है जो पता में मौजूद नहीं है?

यदि हां, तो यह काम कर सकते हैं और तेजी से हो सकता है:

SELECT COUNT(DISTINCT Auditable.UniqueID) 
FROM Auditable 

नोट: यह भी मानता है कि UniqueID पता तालिका में (/ प्राथमिक कुंजी), लेकिन लेखापरीक्षा योग्य तालिका में अद्वितीय नहीं अद्वितीय है

+0

यह मेरे लिए काम नहीं करता है, क्योंकि पते की तुलना में बहुत अधिक ऑडिट योग्य हैं। सभी पतेों में एक ऑडिटेबल होना चाहिए, लेकिन कई अन्य चीजों के लिए ऑडिट योग्य भी हैं। मैं केवल एड्रेस के लिए लेखापरीक्षा की गिनती चाहता हूं। – ibiza

6

यदि आप अक्सर इस क्वेरी को चलाते हैं और इसे सुपर फास्ट होने की आवश्यकता है, तो इसके एक भौतिक अनुक्रमित दृश्य बनाएं। INSERT/UPDATE/DELETEs पर थोड़ा सा ओवरहेड होगा, लेकिन यह क्वेरी तुरंत तत्काल होगी। क्वेरी निष्पादन के दौरान महंगे गणनाओं को कम करने के लिए समेकन को प्रीकंप्यूटेड और इंडेक्स में संग्रहीत किया जा सकता है।

Improving Performance with SQL Server 2005 Indexed Views

+0

+1। ध्यान दें कि दृश्यमान होने के लिए आपको 'COUNT' के बजाय' COUNT_BIG' का उपयोग करना चाहिए। – Quassnoi

+0

टिप के लिए धन्यवाद :) हालांकि यह क्वेरी अक्सर नहीं चलती है, लेकिन मैं निश्चित रूप से उस ज्ञान को – ibiza

+1

के लिए रखूंगा एसक्यूएल ट्यूनिंग को पहले चरण के रूप में जवाबों को शारीरिक रूप से संग्रहीत करने पर भरोसा नहीं करना चाहिए। जवाब को पूरा करना एक अंतिम उपाय होना चाहिए। –

0

विदेशी कुंजी पर सूचकांक गुम, मैं कहूंगा कि।

  • 1.4 मिलियन और 4 मिलियन बड़ी टेबल नहीं हैं, वे छोटे हैं। कृपया 500 मिलियन प्रविष्टियों के माध्यम से बड़े होने पर कहें।

  • एक वास्तविक उत्तर के लिए हमें निष्पादन योजना/क्वेरी योजना की आवश्यकता है, इसलिए हम देख सकते हैं कि क्या होता है।

  • और यह जानना अच्छा होगा कि आपकी दुनिया में "लांग" क्या है (यह देखते हुए कि आपको लगता है कि 4 मिलियन पंक्तियां बहुत हैं)। यह प्रश्न कभी भी 1 सेकंड में जवाब नहीं देगा - तो आप क्या उम्मीद करते हैं और क्या होता है?

  • मैं शर्त लगाता हूं, हालांकि, आपके पास एक अनुपलब्ध अनुक्रमणिका है। उस के शॉर्ट, मैं हार्डवेयर पर इशारा करना शुरू कर दूंगा (क्योंकि मैंने इसे भी देखा है, बकवास प्रदर्शन के कारण के रूप में)।

0

इनमें से बड़ी सारणी के लिए, आप क्वेरी प्रदर्शन बढ़ाने के लिए अपने डेटा को विभाजित करना चाह सकते हैं। साथ ही, यदि आप पहले से नहीं हैं, तो यह देखने के लिए ट्यूनिंग सलाहकार को चलाने का प्रयास करें कि क्या कोई अतिरिक्त इंडेक्स है जो फायदेमंद हो सकता है। इसके अलावा, क्या आपने हाल ही में अपने क्लस्टर इंडेक्स को पुनर्गठित किया है - क्या यह एक ऐसा कार्य है जो रखरखाव पैकेज का हिस्सा है? कई बार, यह आपके प्रदर्शन में भी काफी सुधार करेगा।

2

असली मुद्दा नेस्टेड लूप शामिल है। पता तालिका में प्रत्येक 1.4 मिलियन पंक्तियों के लिए आप एक इंडेक्स कर रहे हैं ऑडिटबल टेबल में खोजें। इसका मतलब है कि 1.4 एम रूट ब्लॉक, शाखा ब्लॉक, और लीफ ब्लॉक कुल 4.2 एम ब्लॉक पढ़ने के लिए पढ़ता है। पूरी अनुक्रमणिका शायद केवल 5 के ब्लॉक है या तो ... इसे एक हैश में शामिल होना चाहिए ताकि यह दोनों इंडेक्स को एक बार पढ़ सके, और उनके माध्यम से हो।

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

+0

मैं ब्लीवल = 2. –

+0

हाय मान रहा हूं और आपकी टिप्पणी के लिए धन्यवाद। मैं 4 जीबी रैम के साथ 4core सीपीयू पर इसे चला रहा हूं ... शीर्ष पर नहीं, लेकिन खराब नहीं – ibiza

+0

लैपटॉप में 4 जीबी रैम है, संभवतः यहां तक ​​कि नेटबुक –

1

क्लॉज EXISTS INNER जॉइन की तुलना में चलाने के लिए कम महंगा है।

select COUNT(adr.UniqueId) 
    from Addresses adr 
    where EXISTS (
     select 1 
      from Auditables aud 
      where aud.UniqueId = adr.UniqueId 
    ) 

क्या यह आपकी आवश्यकता के अनुरूप है?

एनबी। डेटाबेस इंजन के लिए गाइड बहुत महंगा हैं।

+0

धन्यवाद, EXISTS ~ 10% – ibiza

संबंधित मुद्दे