क्या हो रहा है, इसे बेहतर ढंग से समझने के लिए यह प्रयास करें:
explain plan set statement_id = 'query1' for
SELECT count(ck.id)
FROM claim_key ck
WHERE (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
AND ck.clm_type = 5
AND ck.prgrm_id = 1;
और फिर:
select *
from table(dbms_xplan.display(statement_id=>'query1'));
मैं अनुमान लगा रहा हूँ कि आप एक पंक्ति देखेंगे जो दावा_की पर टेबल एक्सेस को पूर्ण रूप से दर्शाती है।
फिर कोशिश करें:
explain plan set statement_id = 'query2' for
SELECT count(ck.id)
FROM claim_key ck
WHERE (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
AND ck.clm_type = 5;
select *
from table(dbms_xplan.display(statement_id=>'query2'));
और यह देखने के लिए जांचें कि यह (संभवतः) किस इंडेक्स का उपयोग कर रहा है। इससे आपको अंदाजा हो जाएगा कि डेटाबेस क्या कर रहा है जो यह पता लगाने में मदद करता है कि क्यों यह कर रहा है।
ठीक है, आपकी व्याख्या योजनाओं को देखते हुए, यह "इंडेक्स हमेशा अच्छे नहीं होते, टेबल स्कैन हमेशा खराब नहीं होते" का एक उत्कृष्ट उदाहरण है।
इंडेक्स स्किप स्कैन वह जगह है जहां डेटाबेस इंडेक्स का उपयोग करने का प्रयास कर सकता है, भले ही इंडेक्स के अग्रणी कॉलम का उपयोग न किया गया हो। मूल रूप से यदि आपकी अनुक्रमणिका इस तरह दिखती है (अत्यधिक सरलीकृत):
COL1 COL2 ROWID
A X 1 <--
A Y 2
A Z 3
B X 4 <--
B Y 5
B Z 6
और आपकी स्थिति थी जहां col2 ='X' इंडेक्स स्किप स्कैन कहता है कि COL1 में प्रत्येक संयोजन को देखें जहां col2 ='X'। यह col1 में मानों को "छोड़ देता है" एक बार जब यह एक मैच (जैसे col1 =A, col2 =X) मिल जाता है, जहां मान बदल जाता है (col1 =B, फिर col1 =C, आदि) और अधिक मिलान की तलाश करता है।पी>
पकड़ यह है कि इंडेक्स (आम तौर पर!) इस तरह काम करते हैं:1) इंडेक्स में अगली पंक्ति को ढूंढें जहां मूल्य पाया गया था 2) उस पंक्ति के साथ टेबल ब्लॉक पर जाएं (इंडेक्स रोविड द्वारा टेबल एक्सेस) 3) तब तक दोहराएं जब तक कोई और मैच न हो पाए जाते हैं।
(स्किप स्कैन के लिए, यह पता लगाने की लागत भी लगेगी कि मूल्य का अगला परिवर्तन अग्रणी कॉलम के लिए कहां है।)
यह सब ठीक है और पंक्तियों की एक छोटी संख्या के लिए अच्छा है, लेकिन ह्रासमान प्रतिफल के नियम से ग्रस्त है; जब आपके पास बड़ी संख्या में पंक्तियाँ हों तो यह बहुत अच्छा नहीं है। ऐसा इसलिए है क्योंकि इसे एक इंडेक्स ब्लॉक, फिर एक टेबल ब्लॉक, फिर एक इंडेक्स ब्लॉक, एक टेबल ब्लॉक (भले ही टेबल ब्लॉक पहले पढ़ा गया हो।)
पूर्ण तालिका स्कैन डेटा के माध्यम से बस "हल" करता है धन्यवाद ... मल्टीब्लॉक पढ़ता है। डेटाबेस एक ही रीड में डिस्क से कई ब्लॉक पढ़ सकता है और एक ही ब्लॉक को एक से अधिक बार नहीं पढ़ता है।
INDEX FAST FULL SCAN मूल रूप से I_CLAIM_KEY_002 को एक तालिका के रूप में मान रहा है। क्वेरी में आपको जो कुछ भी चाहिए, उसका उत्तर केवल इंडेक्स द्वारा दिया जा सकता है; कोई टेबल एक्सेस की आवश्यकता नहीं है। (मुझे लगता है कि I_CLAIM_KEY_002 को clnt_id, dte_of_srvce के रूप में परिभाषित किया गया है और या तो clnt_id या dte_of_srvce अशक्त नहीं है। चूंकि ck.id एक शून्य विशेषता नहीं होनी चाहिए, ck.id पर एक गिनती ck.clnt_id पर गिनती के समान है।)
तो जहाँ तक आपकी प्रारंभिक क्वेरी का सवाल है, जब तक आप अपनी अनुक्रमणिका को फिर से व्यवस्थित नहीं करना चाहते, यह प्रयास करें:
SELECT /*+ FULL(ck) */ count(ck.id)
FROM claim_key ck
WHERE (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
AND ck.clm_type = 5
AND ck.prgrm_id = 1
जो दावा_की (सीके) पर एक पूर्ण तालिका स्कैन को मजबूर करेगा और आप अन्य दो के समान प्रदर्शन देख सकते हैं। (जांचें कि यह मामला पहले "explain plan set Statement_id ='query_hint' for" के साथ क्वेरी को उपसर्ग कर रहा है और इसे चलाने से पहले dbms_xplan क्वेरी चला रहा है।)
(अब आप पूछेंगे "क्या मैं हर समय ऐसे ही संकेत देना चाहता हूं"? कृपया नहीं। यह केवल एक परीक्षण के लिए है। यह सिर्फ यह देखने के लिए है कि क्या FTS इंडेक्स स्किप स्कैन से बेहतर है या नहीं। . अगर ऐसा है, तो आपको इसका पता लगाना होगा। :)
वैसे भी...मुझे आशा है कि यह समझ में आया..मेरा मतलब समझ में आता है।