2010-07-01 15 views
5

मैं एक Oracle 10.2.0.3 डेटाबेस है के लिए गलत प्रमुखता का अनुमान है, और इस तरह एक प्रश्न:ओरेकल योजना की व्याख्या एक सूचकांक रेंज स्कैन

select count(a.id) 
from LARGE_PARTITIONED_TABLE a 
join SMALL_NONPARTITIONED_TABLE b on a.key1 = b.key1 and a.key2 = b.key2 
where b.id = 1000 

टेबल LARGE_PARTITIONED_TABLE (क) के बारे में 5 लाख पंक्तियां हैं, और विभाजित है एक कॉलम द्वारा क्वेरी में मौजूद नहीं है। तालिका SMALL_NONPARTITIONED_TABLE (बी) विभाजित नहीं है, और इसमें लगभग 10000 पंक्तियां हैं।

सांख्यिकी अद्यतित हैं, और स्तंभ कुंजी 1 में ऊंचाई संतुलित हिस्टोग्राम और तालिका ए की कुंजी 2 हैं।

तालिका ए में कॉलम की 1, की 2, की 3, की 4, और की 5 पर एक प्राथमिक कुंजी और गैर-विभाजित अद्वितीय अनुक्रमणिका है।

के बारे में बताएं क्वेरी के लिए योजना प्रदर्शित करता है निम्न परिणाम:

--------------------------------------------------------------------------------------------------- 
| Id | Operation   | Name       | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |        |  1 | 31 |  4 (0)| 00:00:01 | 
| 1 | SORT AGGREGATE |        |  1 | 31 |   |   | 
| 2 | NESTED LOOPS  |        | 406 | 12586 |  4 (0)| 00:00:01 | 
|* 3 | INDEX RANGE SCAN| INDEX_ON_TABLE_B   |  1 | 19 |  2 (0)| 00:00:01 | 
|* 4 | INDEX RANGE SCAN| PRIMARY_KEY_INDEX_OF_TABLE_A | 406 | 4872 |  2 (0)| 00:00:01 | 
--------------------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    3 - access("b"."id"=1000) 
    4 - access("a"."key1"="b"."key1" and 
       "a"."key2"="b"."key2") 

इस प्रकार पंक्तियों (प्रमुखता) चरण 4 के लिए अनुमानित है।

Rows  Row Source Operation 
------- --------------------------------------------------- 
     1 SORT AGGREGATE (cr=51 pr=9 pw=0 time=74674 us) 
    7366 NESTED LOOPS (cr=51 pr=9 pw=0 time=824941 us) 
     1 INDEX RANGE SCAN INDEX_ON_TABLE_B (cr=2 pr=0 pw=0 time=36 us)(object id 111111) 
    7366 INDEX RANGE SCAN PRIMARY_KEY_INDEX_OF_TABLE_A (cr=49 pr=9 pw=0 time=810173 us)(object id 222222) 

तो वास्तविकता में प्रमुखता , नहीं 406 था:

अब, एक tkprof ट्रेस निम्नलिखित का पता चलता है! जहां ओरेकल इस मामले में अनुमान लगाया गया प्रमुखता 406 की प्राप्त करता है से , और मैं इसकी शुद्धता कैसे सुधार सकते हैं ताकि अनुमान क्या वास्तव में क्वेरी निष्पादन के दौरान होता है की पंक्ति में अधिक है:

मेरा प्रश्न यह है ?


अद्यतन: यहाँ एक 10053 ट्रेस मैं क्वेरी पर चलता था का एक टुकड़ा है।

NL Join 
    Outer table: Card: 1.00 Cost: 2.00 Resp: 2.00 Degree: 1 Bytes: 19 
    Inner table: LARGE_PARTITIONED_TABLE Alias: a 
    ... 
    Access Path: index (IndexOnly) 
    Index: PRIMARY_KEY_INDEX_OF_TABLE_A 
    resc_io: 2.00 resc_cpu: 27093 
    ix_sel: 1.3263e-005 ix_sel_with_filters: 1.3263e-005 
    NL Join (ordered): Cost: 4.00 Resp: 4.00 Degree: 1 
     Cost_io: 4.00 Cost_cpu: 41536 
     Resp_io: 4.00 Resp_cpu: 41536 
    ****** trying bitmap/domain indexes ****** 
    Best NL cost: 4.00 
      resc: 4.00 resc_io: 4.00 resc_cpu: 41536 
      resp: 4.00 resp_io: 4.00 resp_cpu: 41536 
Using concatenated index cardinality for table SMALL_NONPARTITIONED_TABLE 
Revised join sel: 8.2891-e005 = 8.4475e-005 * (1/12064.00) * (1/8.4475e-005) 
Join Card: 405.95 = outer (1.00) * inner (4897354.00) * sel (8.2891-e005) 
Join Card - Rounded: 406 Computed: 405.95 

तो वह स्थान जहां से 406 मूल्य आ रहा है। एडम की तरह उत्तर दिया, कार्डिनिटी में शामिल होने join selectivity * filter cardinality (a) * filter cardinality (b) है, जैसा कि उपरोक्त ट्रेस उद्धरण की दूसरी पंक्ति में देखा जा सकता है।

जो मुझे समझ में नहीं आता Revised join sel लाइन है। 1/12064 तालिका बी (तालिका पर 12064 पंक्तियों, और अद्वितीय आईडी के आधार पर चयन) से पंक्ति खोजने के लिए प्रयुक्त सूचकांक की चयनशीलता है। लेकिन तो क्या?

  1. प्रमुखता तालिका के चयनात्मकता एक (1/12064) के साथ फिल्टर तालिका ख (4,897,354) की प्रमुखता गुणा द्वारा गणना प्रतीत होता है। क्यों? क्या पर तालिका एक चयनात्मकता कितना पंक्तियों से तालिका ख पाया होने की उम्मीद है के साथ क्या करना है करता है, जब एक -> ख में शामिल होने a.id पर आधारित नहीं है?

  2. संख्या 8 कहां है।4475e-005 से आते हैं (यह पूरे ट्रेस में कहीं और नहीं दिखाई देता है)? ऐसा नहीं है कि यह आउटपुट को प्रभावित करता है, लेकिन मैं अभी भी जानना चाहता हूं।

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

उत्तर

7

एक 10053 ट्रेस फ़ाइल जेनरेट करने से कार्डिनेलिटी और चुनिंदाता के अनुमान के संबंध में ऑप्टिमाइज़र के क्या विकल्प चुनने में मदद मिलेगी। जोनाथन लुईस 'एक्सेललेक्स्ट लागत आधारित ओरेकल बुनियादी बातों यह समझने के लिए एक उत्कृष्ट संसाधन है कि अनुकूलक कैसे काम करता है, और प्रिंटिंग मैंने 8i से 10.1 तक फैला है।

है कि काम से:

Join Selectivity = ((num_rows(t1) - num_nulls(t1.c1))/num_rows(t1)) 
        * ((num_rows(t2) - num_nulls(t2.c2))/num_rows(t2)) 
       /greater (num_distinct(t1.c1), num_distinct(t2.c2)) 

Join Cardinality = Join Selectivity 
        * filtered_cardinality (t1) 
        * filtered_cardinality (t2) 

हालांकि, क्योंकि हम एक बहु-स्तंभ, में शामिल होने के साथ जुड़ें चयनात्मकता तालिका स्तर पर नहीं है, यह प्रत्येक स्तंभ पर शामिल होने के selectivities के उत्पाद (चौराहे) है। वहाँ यह मानते हुए है खेलने में कोई nulls:

Join Selectivity = Join Selectivity (key1) * Join Selectivity (key2) 

Join Selectivity (key1) = ((5,000,000 - 0)/5,000,000) 
          * ((10,000 - 0))/10,000) 
         /max (116, ?) -- distinct key1 values in B 

         = 1/max(116, distinct_key1_values_in_B) 

Join Selectivity (key2) = ((5,000,000 - 0)/5,000,000) 
          * ((10,000 - 0))/10,000) 
         /max (650, ?) -- distinct key2 values in B 

         = 1/max(650, distinct_key2_values in B) 

Join Cardinality = JS(key1) * JS(key2) 
        * Filter_cardinality(a) * Filter_cardinality(b) 

हम जानते हैं कि एक पर कोई फिल्टर देखते हैं कि, ताकि टेबल फिल्टर प्रमुखता है पंक्तियों की संख्या है।हम बी से महत्वपूर्ण मूल्य है चयन किए जाने वाले हैं, ताकि तालिका के फिल्टर प्रमुखता है 1.

तो के लिए अनुमानित अनुमान प्रमुखता में शामिल होने के लिए सबसे अच्छा मामले अब

Join Cardinality = 1/116 * 1/650 * 5,000,000 * 1 

        =~ 67 

यह पिछड़े काम करने के लिए आसान हो सकता है। 406 की आपकी अनुमानित कार्डिनिटी, जिसे हम जानते हैं, 406/5,000,000, या लगभग 1/12315 के चयन में शामिल होने की ओर जाता है। वास्तव में यह वास्तव में होता है, वास्तव में 1/(116^2) के करीब होता है, जो ऑप्टिमाइज़र के भीतर एक सैनिटी चेक है जो इसे बहु-कॉलम जॉइन पर कार्डिनलिटी को बहुत आक्रामक खोजने से रोकने के लिए करता है।

टी एल के लिए, डॉ भीड़:

  1. जोनाथन लुईस 'लागत के आधार हो जाओ ओरेकल बुनियादी बातों
  2. उस क्वेरी का 10053 ट्रेस प्राप्त करें जिसका व्यवहार आप समझ नहीं सकते।
+0

धन्यवाद एडम। मैं निश्चित रूप से क्वेरी के 10053 ट्रेस पर एक नज़र डालेंगे। कल मेरे परिणाम पोस्ट करेंगे। – Tommi

+0

मैंने अब 10053 ट्रेस के साथ प्रश्न अपडेट किया है, कृपया ऊपर देखें। – Tommi

+1

मैं दूसरे प्रश्न का उत्तर नहीं दे सकता - ओरेकल के बहुत सारे फज कारक हैं, और समेकित सूचकांक कार्डिनिटी नियम अच्छी तरह से प्रलेखित नहीं हैं। इसके अलावा, यह एक कारक है जो खुद को रद्द कर देता है। एबी कार्डिनिटी में शामिल होने वाली बी (4897354) की पूर्ण कार्डिनालिटी द्वारा गुणा किए गए ए (1 पंक्ति) की सापेक्ष कार्डिनालिटी पर आधारित है जो कि चुनिंदाता से गुणा हो जाती है - जो ए की पूर्ण कार्डिनालिटी है इसे देखें मार्ग। आपकी तालिकाएं बी में बी से 48 9 7354 पंक्तियों में 12046 पंक्तियां हैं। इसलिए ए में प्रत्येक पंक्ति के लिए, औसतन 406 पंक्तियां बी –

2

कार्डिनालिटी अनुमान a.key1 और a.key2 की चुनिंदाता के उत्पाद पर आधारित होगा, जो (कम से कम 10 जी) प्रत्येक में दर्ज किए गए दो कॉलम के लिए अलग-अलग मानों की संख्या पर आधारित होगा कॉलम आंकड़े

5 एम पंक्तियों की एक तालिका के लिए, 406 का कार्डिनिटी अनुमान 7366 के लिए काफी अलग नहीं है। सवाल आपको खुद से पूछना है, क्या "गलत" अनुमान यहां समस्या पैदा कर रहा है?

आप देख सकते हैं क्या योजना ओरेकल अगर यह एक इस के लिए योजना की व्याख्या हो रही द्वारा एक पूरी तरह से सटीक अनुमान उत्पन्न करने में सक्षम थे का चयन करेंगे:

select /*+CARDINALITY(a 7366)*/ count(a.id) 
from LARGE_PARTITIONED_TABLE a 
join SMALL_NONPARTITIONED_TABLE b on a.key1 = b.key1 and a.key2 = b.key2 
where b.id = 1000; 

यह एक ही योजना है, तो अनुमान के साथ आता है कि ओरेकल की गणना पहले से ही पर्याप्त है।

+0

धन्यवाद जेफरी। आप निश्चित रूप से सही हैं कि इस उदाहरण में कार्डिनालिटी अनुमान अंतर महत्वपूर्ण नहीं है। हालांकि, यह सिर्फ एक सरल मामला है जिसे मैंने इस प्रश्न के लिए तैयार किया है - मेरे पास समान सारणी के खिलाफ प्रश्नों के अन्य मामले हैं जहां अंतर बहुत बड़ा है - और संभवतः अधिक महत्वपूर्ण भी है। मैं अब भी 406 की कार्डिनालिटी पहुंचने के लिए फॉर्मूला ओरेकल उपयोग के साथ आने में असमर्थ हूं। कॉलम ए और बी के लिए क्रमशः 116 और 650 के लिए Num_distinct हैं। – Tommi

2

आपको वोल्फगैंग ब्रितलिंग द्वारा इस उत्कृष्ट पेपर को पढ़ने में रुचि हो सकती है जिसमें सीबीओ गणनाओं पर बहुत सारी जानकारी है: http://www.centrexcc.com/A%20Look%20under%20the%20Hood%20of%20CBO%20-%20the%2010053%20Event.pdf

जैसा कि समझाया गया है, क्योंकि आपके पास हिस्टोग्राम हैं, इन कॉलमों के लिए फ़िल्टर-कारक गणना अलग-अलग मानों (एनडीवी) की संख्या का उपयोग नहीं करती है, लेकिन घनत्व, जो किसी भी तरह से हिस्टोग्राम से ली गई है।

a.key1 और a.key2 के लिए USER_TAB_COLUMNS में DENSITY मान क्या हैं?

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

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

+0

धन्यवाद डेव, वह पेपर वास्तव में एक दिलचस्प पढ़ने की तरह दिखता है। मुझे इसे थोड़ा पचाने की ज़रूरत है - मैं कल परिणाम पोस्ट करूंगा! – Tommi

+0

मैंने क्वेरी पर एक 10053 ट्रेस चलाया - कृपया अद्यतन प्रश्न देखें। A.key1 और a.key2 के लिए घनत्व मान 0,000000111 और 0,0022831 हैं। – Tommi

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