2009-05-05 16 views
11

मेरे पास एक SQL क्वेरी है जो इस तरह कुछ दिखती है:मैं ओरेकल में row_number कैसे बढ़ा सकता हूं?

SELECT * FROM(
    SELECT 
     ..., 
     row_number() OVER(ORDER BY ID) rn 
    FROM 
     ... 
) WHERE rn between :start and :end 

अनिवार्य रूप से, यह उस भाग से ऑर्डर है जो चीजों को धीमा कर रहा है। अगर मैं इसे हटा देना चाहता था, तो एक्सप्लाइन लागत परिमाण (1000x से अधिक) के क्रम से नीचे जाती है। मैंने यह कोशिश की है:

SELECT 
    ... 
FROM 
    ... 
WHERE 
    rownum between :start and :end 

लेकिन यह सही परिणाम नहीं देता है। क्या इसे गति देने का कोई आसान तरीका है? या मुझे EXPLAIN उपकरण के साथ कुछ और समय बिताना होगा?

उत्तर

12

ROW_NUMBEROracle में काफी अक्षम है।

प्रदर्शन जानकारी के लिए अपने ब्लॉग में लेख देखें:

अपने विशिष्ट क्वेरी के लिए, मुझे लगता है कि सूचकांक प्रयोग किया जाता है आप ROWNUM से बदलने और यह सुनिश्चित करना की सलाह देते हैं :

SELECT * 
FROM (
     SELECT /*+ INDEX_ASC(t index_on_column) NOPARALLEL_INDEX(t index_on_column) */ 
       t.*, ROWNUM AS rn 
     FROM table t 
     ORDER BY 
       column 
     ) 
WHERE rn >= :start 
     AND rownum <= :end - :start + 1 

इस क्वेरी का उपयोग करेगा COUNT STOPKEY

यह भी सुनिश्चित करें कि आप column शून्य नहीं हैं, या WHERE column IS NOT NULL स्थिति जोड़ें।

अन्यथा इंडेक्स का उपयोग सभी मूल्यों को पुनर्प्राप्त करने के लिए नहीं किया जा सकता है।

ध्यान दें कि आप बिना किसी सबक्वायरी के ROWNUM BETWEEN :start and :end का उपयोग नहीं कर सकते हैं।

ROWNUM हमेशा अंतिम और अंतिम चेक किया जाता है, इस तरह ROWNUM हमेशा अंतराल के बिना क्रम में आता है।

आप ROWNUM BETWEEN 10 and 20 उपयोग करते हैं, पहली पंक्ति satisifies सभी अन्य शर्तों लौटने के लिए एक उम्मीदवार, अस्थायी रूप से ROWNUM = 1 साथ सौंपा हो जाते हैं और ROWNUM BETWEEN 10 AND 20 की कसौटी पर असफल हो जायेगी।

फिर अगली पंक्ति एक उम्मीदवार होगी, ROWNUM = 1 और असफल, आदि के साथ असाइन किया जाएगा, इसलिए आखिरकार, कोई पंक्तियां वापस नहीं लौटाई जाएंगी।

यह ROWNUM को सबक्वायरी में डालकर काम किया जाना चाहिए।

+0

काम करता है आकर्षण। हालांकि, ऑप्टिमाइज़र संकेतों में एक सराहनीय अंतर नहीं लग रहा था। –

+3

इसका मतलब है कि 'सीबीओ' इंडेक्स लेने के लिए पर्याप्त स्मार्ट था। वास्तव में यह ROW_NUMBER था जो इसके बजाय ROW_NUMBER था। – Quassnoi

+0

लेकिन मैं अभी भी संकेत छोड़ दूंगा या एक आउटलाइन बनाया होगा, बस सीबीओ अपने दिमाग को बदल देगा :) – Quassnoi

1

क्या आपका ऑर्डर कॉलम द्वारा अनुक्रमित है? यदि यह शुरू करने के लिए एक अच्छी जगह नहीं है।

+0

वास्तव में, यह नहीं था। लेकिन इसे एक पंक्ति में बदलना जो अनुक्रमित है, मदद नहीं कर रहा है। यद्यपि स्पष्ट सुझाव बनाने के लिए धन्यवाद। :-) –

+1

एक इंडेक्स केवल उस आदेश का उपयोग कर सकता है जब एक्सेस पथ उस इंडेक्स का उपयोग कर सकता है (यानी आप आईडी की एक श्रृंखला देख रहे थे)। –

0

EXPLAIN योजना उपकरण के साथ अधिक समय बिताएं। यदि आप एक टेबल स्कैन देखते हैं तो आपको अपनी क्वेरी बदलनी होगी।

आपकी क्वेरी मुझे कम समझ में नहीं आती है। एक ROWID पर पूछताछ परेशानी के लिए पूछने की तरह लगता है। उस क्वेरी में कोई संबंधपरक जानकारी नहीं है। क्या यह वास्तविक सवाल है कि आपको परेशानी हो रही है या एक उदाहरण है जिसे आपने अपनी समस्या का वर्णन करने के लिए बनाया है?

+0

यह अंकन है। और यह अनिवार्य रूप से पेजिंग के साथ क्वेरी क्या करता है। मैंने अभी बाकी की क्वेरी ली है (मुख्य रूप से क्योंकि यह अनौपचारिक है)। सभी अंडाकार हैं जहां मैंने ब्रेवटी के लिए सामान काट दिया है। –

4

मुझे एक पेजिनेशन क्वेरी की तरह दिखता है।

इस ASKTOM लेख से (के बारे में 90 पेज नीचे%):

You need to order by something unique for these pagination queries, so that ROW_NUMBER is assigned deterministically to the rows each and every time.

इसके अलावा अपने प्रश्नों कोई जिसके पास में ही तो कर रहे हैं मुझे यकीन है कि नहीं कर रहा हूँ क्या एक की लागत की तुलना के लाभ दूसरे के लिए है।

+1

वास्तव में, उस आलेख ने मुझे क्वेरी लिखने में मदद की। हालांकि मैंने अद्वितीय आईडी द्वारा ऑर्डर करने के बारे में हिस्सा नहीं देखा। इसके अलावा एक क्वेरी ऑप्टिमाइज़र संकेत है जो मुझे याद आया। मैं कल काम पर कोशिश करूँगा! –

+0

;) सोचा कि यह परिचित लग रहा था। first_rows अंकन प्रश्नों के साथ एक अद्भुत हो सकता है। – David

+0

कि और क्वास्नोई की सलाह ने मेरी क्वेरी को लगभग स्थिर समय तक घटा दिया! काश मैं दो उत्तरों का चयन कर सकता हूं। :-( –

1

समस्या का एक हिस्सा यह है कि 'शुरू' से 'अंत' अवधि और जहां वे 'रहते हैं' कितना बड़ा है। कहें कि आपके पास तालिका में दस लाख पंक्तियां हैं, और आप 567,8 9 0 से 567,900 पंक्तियां चाहते हैं तो आपको इस तथ्य के साथ रहना होगा कि इसे पूरी तालिका में जाने की आवश्यकता होगी, आईडी के द्वारा इसे बहुत अधिक पसंद करें , और उस सीमा में क्या पंक्तियां गिरती हैं, काम करें।

संक्षेप में, कि बहुत काम है, जिसके कारण अनुकूलक यह एक उच्च लागत देता है।

यह कुछ भी सूचकांक में मदद नहीं कर सकता है। एक सूचकांक आदेश देना होगा, लेकिन कम से सबसे अच्छा है, कि तुम कहीं शुरू करने के लिए और फिर आप जब तक आप 567900 प्रवेश करने के लिए मिल पर पढ़ने रखने देता है।

आप अपने अंत उपयोगकर्ता एक समय में 10 आइटम दिखा रहे हैं, तो यह वास्तव में, डीबी से शीर्ष 100 हथियाने कि 100 दस में हिस्सा तो एप्लिकेशन को तोड़ने होने लायक हो सकता है।

+0

यह उचित लगता है। मैं वास्तव में ~ 2 मिलियन रिकॉर्डों में से लगभग 15,000 रिकॉर्ड खींच रहा हूं। हम एक प्रश्न पूछने की अवधि पर सीमित हैं, और एक बार में सभी 15k रिकॉर्ड खींचने से टाइमआउट हो रहा था। इस प्रकार , मैंने सोचा कि परिणामों के माध्यम से पेजिंग इसे रोक देगा। मुझे लगता है कि इसका मतलब है कि मुझे लंबे समय तक अनुरोध करने के लिए नौकरशाही दुःस्वप्न से गुजरना होगा। –

+0

मुझे आशा है कि आप उपयोगकर्ता को 15,000 पंक्तियां नहीं भेज रहे हैं! –

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