2009-12-01 17 views
6

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

ओरेकल में अंतिम n डाले गए रिकॉर्ड का चयन करने का सबसे तेज़ तरीका क्या है, आईडी द्वारा अवरोही क्रम में अंतिम बार क्रमबद्ध (आखिरी बार डाला गया)?

n कुछ अपेक्षाकृत छोटी संख्या है - अभिलेखों की संख्या पृष्ठ पर प्रदर्शित करने के लिए - शायद 50 से भी बड़ा नहीं

टेबल अब दैनिक नए रिकॉर्ड की 10-15 हजारों के साथ 30.000.000 रिकॉर्ड है।

डाटाबेस ओरेकल 10 जी है।

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

select * from MyTable order by primarykeyfield desc 

निष्पादन योजना थी:

--------------------------------------------- 
| Id | Operation   | Name  |  
--------------------------------------------- 
| 0 | SELECT STATEMENT |    | 
| 1 | SORT ORDER BY  |    | 
| 2 | TABLE ACCESS FULL| MyTable  | 
--------------------------------------------- 

मैं हैरान ओरेकल चाहता है कि था सॉर्ट फ़ील्ड पर इंडेक्स होने पर पूर्ण टेबल स्कैन और सॉर्टिंग करने के लिए।

स्वीकृत उत्तर से क्वेरी इंडेक्स का उपयोग करता है और सॉर्ट से बचाता है।

संपादित करें 2:
पुन:। एपीसी की टिप्पणी: सॉर्टिंग वह हिस्सा था जो मुझे आश्चर्यचकित करता था। मुझे उम्मीद थी कि ओरेकल अपेक्षित क्रम में पंक्तियों को पुनः प्राप्त करने के लिए सूचकांक का उपयोग करेगा। क्वेरी के लिये कार्य योजना:

select * from (select * from arh_promjene order by promjena_id desc) x 
    where rownum < 50000000 

बजाय सूचकांक पूर्ण तालिका का उपयोग और प्रकार का उपयोग करता है (ध्यान दें हालत rownum < 50.000.000 - इस तालिका में अभिलेखों की संख्या की तुलना में जिस तरह से अधिक है और Oracle जानता है कि यह मेज से सभी रिकॉर्ड को पुनः प्राप्त करना चाहिए)। इस क्वेरी सभी पंक्तियों रिटर्न पहले प्रश्न के रूप में है, लेकिन कार्य योजना लागू करके निम्नलिखित के साथ:

| Id | Operation      | Name   | 
------------------------------------------------------- 
| 0 | SELECT STATEMENT    |    | 
|* 1 | COUNT STOPKEY    |    | 
| 2 | VIEW      |    | 
| 3 | TABLE ACCESS BY INDEX ROWID| MyTable  | 
| 4 |  INDEX FULL SCAN DESCENDING| SYS_C008809 | 

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

    1 - filter(ROWNUM<50000000)       

यह मेरे लिए असामान्य था कि Oracle इन दो प्रश्नों कि मूलतः एक ही परिणाम सेट लौटने के लिए अलग निष्पादन की योजना बना रहा है।

संपादित करें 3: पुन Amoq की टिप्पणी:

ओरेकल कि 50M पता नहीं है पंक्तियों की संख्या से अधिक है। निश्चित रूप से, में इसके आंकड़े हैं, लेकिन वे पुराने और गलत हो सकते हैं - और ओरेकल कभी भी गलत परिणाम देने की अनुमति दे सकता है क्योंकि आंकड़े गलत हैं।

क्या आप निश्चित हैं? 9 तक की ओरैकल संस्करणों में समय-समय पर आंकड़ों को मैन्युअल रूप से रीफ्रेश करने की अनुशंसा की जाती थी। चूंकि संस्करण 10 ओरेकल स्वचालित रूप से आंकड़े अपडेट करता है। यदि ओरेकल क्वेरी ऑप्टिमाइज़ेशन के लिए इसका उपयोग नहीं करता है तो आंकड़े डेटा का उपयोग क्या है?

+0

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

+0

आपकी क्वेरी * सभी * पंक्तियों के लिए * सभी * कॉलम का चयन करती है। आप आश्चर्यचकित क्यों हैं कि ओरेकल एक पूर्ण टेबल स्कैन करता है? उस क्वेरी को संतुष्ट करने के लिए डेटा और कैसे प्राप्त होगा? – APC

+0

ओरेकल * पता नहीं * कि 50 एम पंक्तियों की संख्या से अधिक है। निश्चित रूप से, इसमें आंकड़े हैं, लेकिन वे पुराने और गलत हो सकते हैं - और ओरेकल * कभी भी गलत परिणाम देने की अनुमति नहीं देगा क्योंकि आंकड़े गलत हैं। –

उत्तर

15

उपयोग ROWNUM:

select 
    * 
from 
    (
    select 
     * 
    from 
     foo 
    order by 
     bork 
    ) x 
where 
    ROWNUM <= n 

ध्यान दें कि rownum एक सबक्वेरी के लिए छँटाई से पहले लागू किया जाता है, जो अन्यथा तुम सिर्फ n यादृच्छिक पंक्तियों मिल जाएगा तुम क्यों दो नेस्टेड प्रश्नों की जरूरत है,।

+0

बिल्कुल ........ –

+0

इसका तात्पर्य है कि बोर सॉर्ट करने योग्य है ... क्या यह ओपी के साथ संगत है? यह बहुत अच्छा हो सकता है लेकिन यदि ऐसा है तो यह अजीब होगा कि ओपी इस तरह के एक साधारण सवाल पूछेगा। –

+1

यदि हम ओपी का अनुक्रमित जेनरेट की गई प्राथमिक कुंजी होने के लिए बोर्क लेते हैं, और मानते हैं कि यह एकान्त रूप से बढ़ रहा है, तो यह क्वेरी काम करेगी। – Dan

4

इसे अद्यतन होने से कई बार देखा जाएगा? अंतिम एन डाली गई पंक्तियों की आईडी की एक और तालिका को रखने के बारे में (इस तालिका से सबसे छोटी आईडी को हटाने के लिए ट्रिगर का उपयोग करें और वर्तमान-सम्मिलित के साथ एक नई पंक्ति जोड़ें)।

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

3

यह आपकी मदद कर सकता है यदि आप क्षेत्रों या तालिका नाम के अलावा और कुछ के नाम .... पता नहीं है

select * from (
    select * from(
    select rownum r,student.* from student where rownum<=(
     select max(rownum) from student 
    ) 
) order by r desc 
) where r<=10; 
3

आप एक सख्ती की जरूरत नहीं है, जहां एक index_desc संकेत

select /*+ index_desc(MyTable,<PK_index>) */ * from MyTable order by primarykeyfield desc 
3

कर मामलों में प्रयास करें बढ़ते क्षेत्र में, आप थिई के अनुमान के रूप में ORA_ROWSCN (सिस्टम चेंज नंबर) का भी उपयोग कर सकते हैं रों।

select * from (select * from student order by ORA_ROWSCN desc) where rownum<10 

सावधानी: इस सटीक नहीं है ओरेकल रिकॉर्ड ब्लॉक में केवल एक SCN, प्रति पंक्ति नहीं के बाद से। यह भी एक पूर्ण टेबल स्कैन करने लगता है - शायद ऑरैकल इस तरह के प्रकार को अनुकूलित करने के लिए पर्याप्त स्मार्ट नहीं है। तो यह उत्पादन के उपयोग के लिए एक अच्छा विचार नहीं हो सकता है।

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