2008-09-29 7 views
14

मान लीजिए कि मेरे पास दो फ़ील्ड, "foo" और "bar" के साथ डेटाबेस तालिका है। उनमें से कोई भी अद्वितीय नहीं है, लेकिन उनमें से प्रत्येक अनुक्रमित हैं। हालांकि, एक साथ अनुक्रमित होने की बजाय, उनमें से प्रत्येक के पास एक अलग इंडेक्स है।एकाधिक इंडेक्स एक साथ काम कर सकते हैं?

अब मान लीजिए कि मैं SELECT * FROM sometable WHERE foo='hello' AND bar='world'; जैसी क्वेरी करता हूं, मेरी तालिका में बड़ी संख्या में पंक्तियां हैं जिनके लिए फू 'हैलो' है और पंक्तियों की एक छोटी संख्या जिसके लिए बार 'दुनिया' है।

तो हुड के तहत करने के लिए डेटाबेस सर्वर के लिए सबसे कुशल चीज बार फ़ील्ड का उपयोग उन सभी क्षेत्रों को खोजने के लिए करती है जहां बार 'दुनिया' है, फिर केवल उन पंक्तियों को वापस करें जिनके लिए foo 'हैलो' है। यह O(n) है जहां एन पंक्तियों की संख्या है जहां बार 'दुनिया' है।

हालांकि, मुझे लगता है यह है कि इस प्रक्रिया, रिवर्स में होगा जहां के लिए सूचकांक इस्तेमाल किया गया था और परिणाम की खोज संभव है। यह O(m) होगा जहां एम पंक्तियों की संख्या है जहां foo 'हैलो' है।

तो ओरेकल कुशलता से यहाँ खोज करने के लिए बहुत चालाक है? अन्य डेटाबेस के बारे में क्या? या क्या कोई तरीका है कि मैं इसे उचित आदेश में खोजने के लिए अपनी क्वेरी में बता सकता हूं? शायद bar='world' डालकर WHERE खंड में पहले?

उत्तर

11

ओरेकल लगभग निश्चित रूप से क्वेरी को चलाने के लिए सबसे चुनिंदा सूचकांक का उपयोग करेगा, और आप इसे समझाए गए योजना के साथ देख सकते हैं।

इसके अलावा, ओरेकल दोनों इंडेक्स के उपयोग को दो तरीकों से जोड़ सकता है - यह बिट्री इंडेक्स को बिटमैप्स में परिवर्तित कर सकता है और उन पर बिटमैप एएनडी ऑपरेशन कर सकता है, या यह एक हैश को रैडिड पर वापस लौटा सकता है दो इंडेक्स

यहां एक महत्वपूर्ण विचार पूछे जाने वाले मूल्यों के बीच कोई सहसंबंध हो सकता है। यदि foo = 'हैलो' तालिका में 80% मानों और बार = 'दुनिया' खातों के लिए 10% के लिए खाते हैं, तो ओरेकल अनुमान लगाने जा रहा है कि क्वेरी तालिका पंक्तियों के 0.8 * 0.1 = 8% वापस आ जाएगी। हालांकि यह सही नहीं हो सकता है - क्वेरी वास्तव में मूल्यों से संबंधित कैसे हैं, इस पर निर्भर करता है कि पंक्तियों में से 10% या पंक्तियों का 0% भी वापस आ सकता है। अब, तालिका में उन पंक्तियों के वितरण के आधार पर उन्हें खोजने के लिए एक अनुक्रमणिका का उपयोग करने में सक्षम नहीं हो सकता है। आपको अभी भी आवश्यक पंक्तियों ("क्लस्टरिंग कारक" के लिए Google) को पुनर्प्राप्त करने के लिए 70% या तालिका ब्लॉक तक पहुंचने की आवश्यकता हो सकती है, जिस स्थिति में ओरेकल एक पूर्ण तालिका स्कैन करने जा रहा है यदि यह अनुमान सही हो।

11 जी में आप इस स्थिति के साथ मदद करने के लिए बहुआयामी आंकड़े एकत्र कर सकते हैं। 9i और 10g में आप पंक्तियों की संख्या को पुनर्प्राप्त करने के लिए बहुत अच्छा अनुमान प्राप्त करने के लिए गतिशील नमूनाकरण का उपयोग कर सकते हैं।

कार्य योजना लागू करके यह कर पाने के लिए:

explain plan for 
SELECT * 
FROM sometable 
WHERE foo='hello' AND bar='world' 
/
select * from table(dbms_xplan.display) 
/

कंट्रास्ट उस के साथ:

explain plan for 
SELECT /*+ dynamic_sampling(4) */ 
     * 
FROM sometable 
WHERE foo='hello' AND bar='world' 
/
select * from table(dbms_xplan.display) 
/
+1

सभी के साथ डेविड का सम्मान करें, नीचे एली की टिप्पणियों को देखते हुए, उनके प्रश्न का उत्तर "बिटमैप्स का उपयोग करें"। –

+1

बिटमैप इंडेक्स निश्चित हैं इस प्रकार की क्वेरी पर ly कुशल है, लेकिन वे वास्तव में एक OLTP वातावरण में असभ्य हैं। यह जानने के लायक भी है कि बिट्री इंडेक्स की एक जोड़ी को बिटमैप ऑपरेशन में जोड़ा जा सकता है, हालांकि इस पर बहुत अधिक ओवरहेड है। –

3

हाँ, आप Oracle करने के लिए क्वेरी के साथ "संकेत" दे सकते हैं। इन संकेतों को डेटाबेस में टिप्पणियों ("/ * HINT * /") के रूप में छिपाया जाता है और मुख्य रूप से विक्रेता विशिष्ट होते हैं। तो एक डेटाबेस के लिए एक संकेत अन्य डेटाबेस पर काम नहीं करेगा।

मैं सूचकांक संकेत यहाँ छोटी सी मेज के लिए प्रयोग करेंगे, पहले संकेत। here देखें।

दूसरी ओर, यदि आप अक्सर इन दो क्षेत्रों पर खोजते हैं, क्यों नहीं इन दोनों पर एक सूचकांक बनाने? मेरे पास सही वाक्यविन्यास नहीं है, लेकिन यह

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo); 

कुछ ऐसा होगा जैसे डेटा पुनर्प्राप्ति बहुत तेज होनी चाहिए। और यदि संगतता अद्वितीय है तो आप बस एक अद्वितीय इंडेक्स बनाते हैं जो बिजली को तेजी से होना चाहिए।

+0

इनफॉर्मिक्स में इन संकेत खंड भी हैं। अधिकांश समय आप इस विकल्प को _help_ नहीं जा रहे हैं - यह बहुत अच्छा है कि यह क्या करता है। – hometoast

+0

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

+0

क्षमा मांगने की भी कोशिश न करें:)। ओरेकल शायद आपके मामले में "सबसे संवेदनशील" का उपयोग करेगा। फिर, आपको अकेले ओरेकल के अनुकूलन पर भरोसा नहीं करना चाहिए। लेकिन, एक बात के लिए, व्याख्या योजना को अद्यतन करना और इसे अद्यतित रखने की कोशिश करना एक अच्छा विचार है, वैसे भी। – Georgi

2

तो ओरेकल स्मार्ट को कुशलता से यहां खोजने के लिए पर्याप्त स्मार्ट है?

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

1

मुझे यकीन है कि आप ओरेकल को एक क्वेरी प्लान भी प्रदर्शित कर सकते हैं ताकि आप देख सकें कि वास्तव में कौन सी अनुक्रमणिका का उपयोग किया जाता है।

+0

"योजना" बस यही है, जो पहले करने की योजना है। ऐसे समय होते हैं जब वास्तव में जो होता है उससे विचलित होता है। वास्तव में क्या हुआ यह जानने के लिए आपको एक ट्रेस उत्पन्न करने की आवश्यकता है। –

1

आप संकेत दे सकते हैं कि किस सूचकांक का उपयोग करना है। मैं ओरेकल से परिचित नहीं हूं, लेकिन माइस्क्ल में आप यूएसई | इग्नोर | FORCE_INDEX का उपयोग कर सकते हैं (अधिक जानकारी के लिए here देखें)। सर्वोत्तम प्रदर्शन के लिए हालांकि आपको संयुक्त सूचकांक का उपयोग करना चाहिए।

1

सबसे अच्छा तरीका बार की अनुक्रमणिका में foo जोड़ने, या foo's index (या दोनों) में बार जोड़ने के लिए होगा। अगर फू इंडेक्स में बार पर एक इंडेक्स भी शामिल है, तो अतिरिक्त इंडेक्सिंग स्तर उस इंडेक्स के किसी भी मौजूदा उपयोग में फू इंडेक्स की उपयोगिता को प्रभावित नहीं करेगा, न ही यह उस इंडेक्स को बनाए रखने के प्रदर्शन को सराहना करेगा, लेकिन यह डेटाबेस को अतिरिक्त देगा उदाहरण में जैसे अनुकूलन प्रश्नों के साथ काम करने के लिए जानकारी।

+0

दरअसल मैं जेफरी के साथ सहमत हूं ... उन्होंने जो कहा है उसके अलावा, दो अलग-अलग सूचकांक होने से आपकी लेखन गति प्रभावित होगी (क्योंकि डेटाबेस को एक के बजाय लिखने पर दो सूचकांक अपडेट करना होगा। –

1

यह उससे बेहतर है।

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

+1

सबसे पहले, यह सच नहीं है कि अनुक्रमणिका पूरी टेबल स्कैन की तुलना में हमेशा तेज़ होते हैं। ओरेकल में, पूर्ण तालिका स्कैन के लिए बहु-ब्लॉक पढ़ता है यदि आप पंक्तियों के एक छोटे से हिस्से को पुनर्प्राप्त कर रहे हैं तो इंडेक्स के सिंगल-ब्लॉक रीड से तेज़ हो सकते हैं। –

+1

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

2

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

कम से कम, यदि अनुकूलक किसी विशेष स्थिति की चयनकता निर्धारित करने में सक्षम है, तो यह अधिक चुनिंदा सूचकांक (यानी बार पर सूचकांक) का उपयोग करेगा। लेकिन यदि आपके पास डेटा खराब है (कॉलम बार में एन मान हैं लेकिन किसी भी विशेष मूल्य की चुनिंदाता डेटा के 1/एन से काफी कम या कम है), तो आपको कॉलम पर हिस्टोग्राम रखना होगा अनुकूलक जो मान कम या ज्यादा संभावना है। और यदि आप ओरेकल संस्करण के आधार पर बाध्य चर (जैसे सभी अच्छे OLTP डेवलपर्स को चाहिए) का उपयोग कर रहे हैं, तो आपको बाध्य परिवर्तनीय peeking के साथ समस्या हो सकती है।

संभावित रूप से, ओरेकल दो बी * -ट्री इंडेक्स के फ्लाई रूपांतरण पर बिटमैप्स तक भी कर सकता है और बिट्स को गठबंधन कर सकता है ताकि दोनों इंडेक्स का उपयोग करने के लिए पंक्तियों को खोजने के लिए उपयोग किया जा सके। लेकिन यह एक असामान्य क्वेरी योजना है, खासकर यदि केवल दो कॉलम हैं जहां एक कॉलम अत्यधिक चुनिंदा है।

+0

अंक ले लिया। एक सोचता है कि डेटाबेस अनुकूलक डिफ़ॉल्ट रूप से आकार की तुलना करेगा। –

3

एली,

एक टिप्पणी में आप ने लिखा है:

दुर्भाग्य से, मैं अपने स्वयं के सूचकांक के साथ कॉलम प्रत्येक के बहुत सारे के साथ एक मेज है। उपयोगकर्ता फ़ील्ड के किसी भी संयोजन से पूछताछ कर सकते हैं, इसलिए मैं प्रत्येक फ़ील्ड संयोजन पर कुशलता से इंडेक्स नहीं बना सकता।लेकिन अगर मेरे पास केवल दो फ़ील्ड इंडेक्स की आवश्यकता है, तो मैं दो इंडेक्स का उपयोग करने के लिए आपके सुझाव से पूरी तरह से सहमत हूं। - एली कोर्टवाइट (2 9 सितंबर को 15:51)

यह वास्तव में बल्कि महत्वपूर्ण जानकारी है। कभी-कभी प्रोग्रामर प्रश्न पूछते समय खुद को बाहर निकाल देते हैं। वे सवाल को मौलिक बिंदुओं तक सीमित करने की कोशिश करते हैं, लेकिन अक्सर सरलता प्राप्त करने और सबसे अच्छा जवाब प्राप्त करने से चूक जाते हैं।

यह परिदृश्य ठीक है कि बिटमैप इंडेक्स का आविष्कार क्यों किया गया था - उस समय को संभालने के लिए जब कॉलम के अज्ञात समूह का उपयोग किसी खंड में किया जाएगा।

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

+1

मैंने सभी टिप्पणियों को पढ़ा और आश्चर्यचकित किया कि कोई भी यह क्यों नहीं कह रहा था कि बिटमैप्स का आविष्कार क्यों किया गया था। +1 –

+0

जानकारी के लिए धन्यवाद; मैंने कभी भी बिटमैप इंडेक्स के बारे में कभी नहीं सुना होगा, इसलिए मैं उन्हें देख लूंगा। इस परियोजना पर हमारे वर्तमान इंडेक्स डिज़ाइन को बदलने में बहुत देर हो सकती है, लेकिन यदि हमारे पास प्रदर्शन समस्याएं हैं तो मैं बीएमआई में वापस आऊंगा और निश्चित रूप से भविष्य की परियोजनाओं पर उनका उपयोग करने का प्रयास करूंगा। –