2008-10-07 14 views
5

बस की सुविधा देता है कहते हैं कि तुम Oracle में एक मेज है:ओरेकल 10+ में एनयूएलएल वाले कॉलम पर फ़ंक्शन-आधारित इंडेक्स का उपयोग कैसे करें?

CREATE TABLE person (
    id NUMBER PRIMARY KEY, 
    given_names VARCHAR2(50), 
    surname VARCHAR2(50) 
); 
इन समारोह आधारित सूचकांक के साथ

:

CREATE INDEX idx_person_upper_given_names ON person (UPPER(given_names)); 
CREATE INDEX idx_person_upper_last_name ON person (UPPER(last_name)); 

अब, given_names कोई शून्य मान हैं लेकिन तर्क की खातिर last_name करता है के लिए। मैं ऐसा करते हैं तो:

SELECT * FROM person WHERE UPPER(last_name) LIKE 'P%' 

यह नहीं है:

SELECT * FROM person WHERE UPPER(given_names) LIKE 'P%' 

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

मैं इन प्रश्नों की कोशिश की है:

SELECT * FROM person WHERE UPPER(last_name) LIKE 'P%' AND UPPER(last_name) IS NOT NULL 

और

SELECT * FROM person WHERE UPPER(last_name) LIKE 'P%' AND last_name IS NOT NULL 

उत्तरार्द्ध मामले में मैं भी last_name पर एक सूचकांक जोड़ा है, लेकिन कोई फर्क नहीं पड़ता कि मैं क्या करने की कोशिश यह एक पूर्ण तालिका स्कैन का उपयोग करता है। मान लीजिए कि मैं नल मानों से छुटकारा नहीं पा रहा हूं, मैं इस क्वेरी को UPPER (last_name) पर इंडेक्स का उपयोग करने के लिए कैसे प्राप्त करूं?

+0

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

उत्तर

7

सूचकांक, इस्तेमाल किया जा सकता है, हालांकि अनुकूलक अपने विशेष उदाहरण के लिए इसका इस्तेमाल करने के लिए नहीं चुना है हो सकता है:

SQL> create table my_objects 
    2 as select object_id, object_name 
    3 from all_objects; 

Table created. 

SQL> select count(*) from my_objects; 
    2/

    COUNT(*) 
---------- 
    83783 


SQL> alter table my_objects modify object_name null; 

Table altered. 

SQL> update my_objects 
    2 set object_name=null 
    3 where object_name like 'T%'; 

1305 rows updated. 

SQL> create index my_objects_name on my_objects (lower(object_name)); 

Index created. 

SQL> set autotrace traceonly 

SQL> select * from my_objects 
    2 where lower(object_name) like 'emp%'; 

29 rows selected. 


Execution Plan 
---------------------------------------------------------- 

------------------------------------------------------------------------------------ 
| Id | Operation     | Name   | Rows | Bytes | Cost (%CPU)| 
------------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT   |     | 17 | 510 | 355 (1)| 
| 1 | TABLE ACCESS BY INDEX ROWID| MY_OBJECTS  | 17 | 510 | 355 (1)| 
|* 2 | INDEX RANGE SCAN   | MY_OBJECTS_NAME | 671 |  |  6 (0)| 
------------------------------------------------------------------------------------ 

प्रलेखन आप पढ़ रहा था शायद कि उनका कहना है, किसी भी अन्य सूचकांक की तरह, सब शून्य कुंजी को इंडेक्स में संग्रहीत नहीं किया जाता है।

2

आपके उदाहरण में आपने दो बार एक ही इंडेक्स बनाया है - इससे कोई त्रुटि होगी, इसलिए मुझे लगता है कि चिपकने में गलती थी, न कि आपके द्वारा किए गए वास्तविक कोड।

मैं

CREATE INDEX idx_person_upper_surname ON person (UPPER(surname)); 

SELECT * FROM person WHERE UPPER(surname) LIKE 'P%'; 

के साथ की कोशिश की और यह उम्मीद क्वेरी योजना का उत्पादन:

Execution Plan 
---------------------------------------------------------- 
    0  SELECT STATEMENT Optimizer=ALL_ROWS (Cost=1 Card=1 Bytes=67) 
    1 0 TABLE ACCESS (BY INDEX ROWID) OF 'PERSON' (TABLE) (Cost=1 
      Card=1 Bytes=67) 

    2 1  INDEX (RANGE SCAN) OF 'IDX_PERSON_UPPER_SURNAME' (INDEX) 
      (Cost=1 Card=1) 

आपके प्रश्न का उत्तर करने के लिए, हाँ यह काम करना चाहिए। दोहरी जांच करने का प्रयास करें कि आपके पास दूसरी अनुक्रमणिका सही ढंग से बनाई गई है।

इसके अलावा एक स्पष्ट संकेत का प्रयास करें:

SELECT /*+INDEX(PERSON IDX_PERSON_UPPER_SURNAME)*/ * 
FROM person 
WHERE UPPER(surname) LIKE 'P%'; 

अगर वह काम करता है, लेकिन केवल संकेत के साथ तो बहुत संभव है गलत हो गया सीबीओ सांख्यिकी, या सीबीओ संबंधित init मानकों से संबंधित है।

+0

क्या आपने एनयूएलएल को टेबल में रखा था और वह क्वेरी प्लान प्राप्त किया था? – cletus

0

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

0

आप शून्य मान की समस्या को दरकिनार कर सकते हैं द्वारा इस या अन्य स्थितियों में unindexed जा रहा है यह भी एक शाब्दिक मूल्य के आधार पर का अनुक्रमण:

:

CREATE INDEX idx_person_upper_surname ON person (UPPER(surname),0); 

यह आप के रूप में इस तरह के प्रश्नों के लिए सूचकांक का उपयोग करने की अनुमति देता है

Select * 
From person 
Where UPPER(surname) is null; 

यह क्वेरी आमतौर पर उपनाम के अलावा एक गैर-अनुपलब्ध वास्तविक कॉलम सहित बिटमैप इंडेक्स या इंडेक्स को छोड़कर एक सूचकांक नहीं होगी।

+0

डेविड, इस तरह की एक इंडेक्स का किस प्रकार की क्वेरी का उपयोग कर सकता है? –

+1

कोई भी क्वेरी जो UPPER (उपनाम) का उपयोग करती है। डेविड की चाल यह सुनिश्चित करती है कि UPPER (उपनाम) के शून्य मान अनुक्रमित हैं। यदि सभी मान शून्य हैं तो ओरेकल इंडेक्स नहीं करता है। 0 का शाब्दिक मान यह सुनिश्चित करता है कि यह कभी नहीं होता है। –

0

ओरेकल अभी भी कॉलम वाले फ़ंक्शन-आधारित इंडेक्स का उपयोग करेगा जिसमें शून्य है - मुझे लगता है कि आपने दस्तावेज़ों का गलत व्याख्या किया है।

यदि आप इसके लिए जांच करना चाहते हैं तो आपको फ़ंक्शन इंडेक्स में एक nvl डालना होगा।

कुछ की तरह ...

create index idx_person_upper_surname on person (nvl(upper(surname),'N/A')); 

इसके बाद आप क्वेरी सूचकांक का उपयोग कर सकते हैं

select * from person where nvl(upper(surname),'N/A') = 'PIERPOINT' 

हालांकि साथ, सभी एक सा बदसूरत। चूंकि अधिकांश लोगों के उपनाम हैं, शायद एक "शून्य नहीं" उपयुक्त है :-)।

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