2010-06-24 12 views
6

तो मैं कुछ बेहद बड़ी तालिकाओं से पूछताछ कर रहा हूं। वे इतने बड़े कारण हैं क्योंकि मौजूदा रिकॉर्ड अपडेट करने के बजाए पीपल्स सॉफ्ट कुछ डेटा में बदलाव किए जाने पर नए रिकॉर्ड डालता है। असल में, इसकी लेनदेन तालिका भी एक डेटा वेयरहाउस हैं।प्रभावी डेटा वाले डेटा के साथ विशाल डेटा गोदाम तालिकाओं के खिलाफ प्रश्नों को कैसे बढ़ाया जा सकता है?

यह सबसे हालिया/वर्तमान पंक्ति प्राप्त करने के लिए उन प्रश्नों की आवश्यकता है जो नेस्टेड चुनते हैं। वे दोनों प्रभावी दिनांकित हैं और प्रत्येक तारीख के भीतर (एक दिन में कास्ट) उनके पास एक प्रभावी अनुक्रम हो सकता है। इस प्रकार, आदेश user_id=123 के लिए मौजूदा रिकॉर्ड प्राप्त करने के लिए, मैं यह करने के लिए है:

select * from sometable st 
where st.user_id = 123 
and st.effective_date = (select max(sti.effective_date) 
    from sometable sti where sti.user_id = st.user_id) 
and st.effective_sequence = (select max(sti.effective_sequence) 
    from sometable sti where sti.user_id = st.user_id 
    and sti.effective_date = st.effective_date) 

इन तालिकाओं पर अनुक्रमणिका के एक अभूतपूर्व संख्या में हैं, और मैं कुछ और है कि मेरे प्रश्नों में तेजी लाने के हैं नहीं मिल सकता है ।

मेरे दिक्कत यह है कि मैं अक्सर कई बार हो सकता है 50 user_ids के लिए इन तालिकाओं से एक व्यक्ति के बारे में डेटा प्राप्त करना चाहते हैं, लेकिन जब मैं इन पीपुलसॉफ्ट टेबल के कुछ ही साथ उन में केवल कुछ ही रिकॉर्ड होने मेरी टेबल में शामिल होने, चीज़ें बस जाओ है अनुचित व्यवहार।

पीपुल्स सॉफ्ट टेबल दूरस्थ डेटाबेस पर हैं जो मैं डेटाबेस लिंक के माध्यम से उपयोग करता हूं। मेरे प्रश्न इस तरह दिखते हैं:

select st.* from local_table lt, [email protected] st 
where lt.user_id in ('123', '456', '789') 
and lt.user_id = st.user_id 
and st.effective_date = (select max(sti.effective_date) 
    from [email protected] sti where sti.user_id = st.user_id) 
and st.effective_sequence = (select max(sti.effective_sequence) 
    from [email protected] sti where sti.user_id = st.user_id 
    and sti.effective_date = st.effective_date) 

जब मुझे अपनी स्थानीय तालिका के साथ कई पीपुल्स सॉफ्ट टेबल में शामिल होना होता है तो चीजें और भी बदतर होती हैं। प्रदर्शन सिर्फ अस्वीकार्य है।

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

मान लीजिए कि मेरे पास पीपल्स सॉफ्ट और मेरी टेबल का स्थान बदलने की शक्ति नहीं है, मेरी सबसे अच्छी पसंद का संकेत है? अगर मैं चार रिमोट टेबल के साथ एक स्थानीय टेबल में शामिल हो रहा था, और स्थानीय तालिका उनमें से दो के साथ जुड़ गई, तो मैं संकेत कैसे प्रारूपित करूं ताकि मेरी स्थानीय तालिका (जो बहुत छोटी है - वास्तव में, मैं सिर्फ एक इनलाइन दृश्य कर सकता हूं मेरी स्थानीय तालिका केवल उस उपयोगकर्ता_आईड्स के लिए है जिसमें मुझे रूचि है) पहले रिमोट वाले प्रत्येक के साथ जुड़ गया है?

संपादित करें: एप्लिकेशन को रीयल-टाइम डेटा की आवश्यकता है, दुर्भाग्यवश एक भौतिक दृश्य या कैशिंग डेटा की अन्य विधि पर्याप्त नहीं होगी।

+2

+1, डीबी लिंक पर शामिल होने का सामना करने वाले किसी भी व्यक्ति को इसकी सराहना करने में सक्षम होना चाहिए। – DCookie

+0

क्या आप इन प्रश्नों के लिए व्याख्या योजना पोस्ट कर सकते हैं? – APC

+1

यदि आपका डीबी उत्सुक अपडेट का समर्थन करता है तो आप भौतिक दृश्यों का उपयोग करने में सक्षम हो सकते हैं। –

उत्तर

4

क्या आपकी मदद कुछ इस तरह की मदद से दोबारा कर रहा है?

SELECT * 
    FROM (SELECT st.*, MAX(st.effective_date) OVER (PARTITION BY st.user_id) max_dt, 
        MAX(st.effective_sequence) OVER (PARTITION BY st.user_id, st.effective_date) max_seq 
      FROM local_table lt JOIN [email protected] st ON (lt.user_id = st.user_id) 
     WHERE lt.user_id in ('123', '456', '789')) 
WHERE effective_date = max_dt 
    AND effective_seq = max_seq; 

मुझे लगता है कि प्रदर्शन डीबी लिंक से अधिक में शामिल होने वास्तव में चूसना कर सकते हैं और आप क्या आप इस दृष्टिकोण के साथ पूरा कर सकते हैं में सीमित हो की संभावना हो @Mark बेकर के साथ सहमत हैं।

+0

मुझे नहीं पता कि यह आंतरिक रूप से कैसे काम करता है लेकिन यह मुझे मेरी मूल क्वेरी पर एक महत्वपूर्ण प्रदर्शन लाभ देता है। –

+0

मुझे निश्चित रूप से पता नहीं है, लेकिन मेरा आंत महसूस होता है कि आपके सभी खंडों में से प्रत्येक में रिमोट डीबी पर एक अलग क्वेरी उत्पन्न हो रही थी, जबकि यह क्वेरी एक हिट के साथ सब कुछ प्राप्त करती है। – DCookie

0

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

SELECT 
    ST1.col1, 
    ST1.col2, 
    ... 
FROM 
    Some_Table ST1 
LEFT OUTER JOIN Some_Table ST2 ON 
    ST2.user_id = ST1.user_id AND 
    (
     ST2.effective_date > ST1.effective_date OR 
     (
      ST2.effective_date = ST1.effective_date AND 
      ST2.effective_sequence > ST1.effective_sequence 
     ) 
    ) 
WHERE 
    ST2.user_id IS NULL 

एक अन्य संभावित समाधान होगा:

SELECT 
    ST1.col1, 
    ST1.col2, 
    ... 
FROM 
    Some_Table ST1 
WHERE 
    NOT EXISTS 
    (
     SELECT 
     FROM 
      Some_Table ST2 
     WHERE 
      ST2.user_id = ST1.user_id AND 
      (
       ST2.effective_date > ST1.effective_date OR 
       (
        ST2.effective_date = ST1.effective_date AND 
        ST2.effective_sequence > ST1.effective_sequence 
       ) 
      ) 
    ) 
0

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

इसके अलावा, इस बात पर निर्भर करता है कि क्या आपके पास नवीनतम डेटा और उपलब्ध होने के बीच 1 दिन का अंतराल हो सकता है या नहीं।

मैं Oracle के साथ सुपर परिचित तो वहाँ एक रास्ता भी आपकी क्वेरी में परिवर्तन करके सुधार लाने के लिए हो सकता है नहीं कर रहा हूँ ...

1

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

+0

मुझे विचार पसंद है, लेकिन डेटा को वास्तविक समय होना चाहिए। –

+0

फिर दूरस्थ डीबी में एक भौतिक दृश्य पर विचार करें जो प्रत्येक उपयोगकर्ता आईडी के लिए सबसे हाल की पंक्ति सूचीबद्ध करता है। इससे रिमोट लिंक पर चलने वाले डेटा की मात्रा कम हो जाएगी। – Karl

1

प्रदर्शन समस्या लिंक के पार पहुंचने जा रही है। स्थानीय तालिकाओं के खिलाफ पूछताछ के हिस्से के साथ, यह सब स्थानीय रूप से निष्पादित किया जा रहा है, इसलिए रिमोट इंडेक्स तक कोई पहुंच नहीं है और यह सभी रिमोट डेटा को वापस ले जाने के लिए खींच रहा है।

यदि आप ऐतिहासिक डेटा के लिए आवधिक (रात) आधार पर लोगों के डेटाबेस से रीफ्रेश किए गए स्थानीय डेटाबेस में भौतिक दृश्यों का उपयोग कर सकते हैं, तो आज के परिवर्तनों के लिए केवल दूरस्थ लोगों के डेटाबेस तक पहुंच सकते हैं (एक प्रभावी_डेट = आज आपके खंड में) और दो प्रश्न विलय।

एक और विकल्प दूरस्थ डेटा के लिए केवल एक अस्थायी स्थानीय तालिका या भौतिक दृश्य में खींचने के लिए एक्स चयन में उपयोग करने के लिए हो सकता है, फिर आपके स्थानीय डेटा के साथ जुड़ने के लिए दूसरी क्वेरी ... josephj1989 के समान सुझाव

वैकल्पिक रूप से (हालांकि लाइसेंसिंग समस्याएं हो सकती हैं) आरएसी को अपने स्थानीय डीबी को दूरस्थ लोगों के डीबी के साथ क्लस्टर करने का प्रयास करें।

3

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

केवल जरूरत अनुक्रमित आपके प्रश्नों का समर्थन और इस पर अपनी क्वेरी करने बनाने

with remote_query as 
(
    select /*+ materialize */ st.* from [email protected] st 
    where st.user_id in ('123', '456', '789') 
    and st.rowid in(select first_value(rowid) over (order by effective_date desc, 
         effective_sequence desc) from [email protected] st1 
         where st.user_id=st1.user_id) 
) 

select lt.*,st.* 
FROM local_table st,remote_query rt 
where st.user_id=rt.user_id 
+1

+1, विश्लेषणात्मक के आपके उपयोग की तरह। मुझे लगता है कि आप यूजर_आईडी की एक हार्ड कोडेड सूची को अपने खंड में निर्दिष्ट किया जा सकता है, यह मानने में थोड़ा धोखा दे सकता है, हालांकि - यदि यह आसान था, तो आपको पहले स्थान पर स्थानीय_टेबल में शामिल होने की आवश्यकता नहीं होगी। – DCookie

0

आप अपने खुद के तालिका में वांछित user_id के साथ पंक्तियों ईटीएल कर सकते हैं नीचे देखें,?

0

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

यदि आप तालिका पर अनुक्रमणिका जानते हैं, तो आप ओरेकल संकेतों का उपयोग करने के लिए एक पसंदीदा इंडेक्स निर्दिष्ट करने के लिए उपयोग कर सकते हैं; कभी-कभी मदद करता है।

क्या आपने यह निर्धारित करने के लिए एक योजना बनाई है कि क्या आप यह निर्धारित कर सकते हैं कि समस्या कहां है? शायद एक कार्टशियन शामिल है, पूर्ण टेबल स्कैन, आदि?

4

एक दृष्टिकोण पीएल/एसक्यूएल कार्यों को सबकुछ के आसपास रखना होगा। एक उदाहरण

create table remote (user_id number, eff_date date, eff_seq number, value varchar2(10)); 

create type typ_remote as object (user_id number, eff_date date, eff_seq number, value varchar2(10)); 
. 
/

create type typ_tab_remote as table of typ_remote; 
. 
/

insert into remote values (1, date '2010-01-02', 1, 'a'); 
insert into remote values (1, date '2010-01-02', 2, 'b'); 
insert into remote values (1, date '2010-01-02', 3, 'c'); 
insert into remote values (1, date '2010-01-03', 1, 'd'); 
insert into remote values (1, date '2010-01-03', 2, 'e'); 
insert into remote values (1, date '2010-01-03', 3, 'f'); 

insert into remote values (2, date '2010-01-02', 1, 'a'); 
insert into remote values (2, date '2010-01-02', 2, 'b'); 
insert into remote values (2, date '2010-01-03', 1, 'd'); 

create function show_remote (i_user_id_1 in number, i_user_id_2 in number) return typ_tab_remote pipelined is 
    CURSOR c_1 is 
    SELECT user_id, eff_date, eff_seq, value 
    FROM 
     (select user_id, eff_date, eff_seq, value, 
         rank() over (partition by user_id order by eff_date desc, eff_seq desc) rnk 
     from remote 
     where user_id in (i_user_id_1,i_user_id_2)) 
    WHERE rnk = 1; 
begin 
    for c_rec in c_1 loop 
     pipe row (typ_remote(c_rec.user_id, c_rec.eff_date, c_rec.eff_seq, c_rec.value)); 
    end loop; 
    return; 
end; 
/

select * from table(show_remote(1,null)); 

select * from table(show_remote(1,2)); 

बजाय होने user_id के पैरामीटर के रूप में व्यक्तिगत रूप से पारित कर दिया है, तो आप उन्हें एक स्थानीय तालिका (जैसे एक वैश्विक अस्थायी तालिका) में लोड कर सकते हैं। पीएल/एसक्यूएल तब टेबल के माध्यम से लूप करेगा, स्थानीय तालिका में प्रत्येक पंक्ति के लिए दूरस्थ चयन कर रहा है। स्थानीय और दूरस्थ दोनों टेबलों में कोई भी क्वेरी नहीं होगी। प्रभावी रूप से आप अपना स्वयं का कोड लिखेंगे।

+0

+1 मुझे आपकी सोच –

+0

+1 पसंद है, अब, कुछ पूरी तरह से अलग ... – DCookie

0

यह मुझे लगता है कि आप डेटा गोदाम में एक प्रकार 2 आयाम से निपट रहे हैं। टाइप 2 आयाम को कार्यान्वित करने के कई तरीके हैं, जिनमें ज्यादातर ValidFrom, ValidTo, Version, Status जैसे कॉलम हैं। वे सभी हमेशा मौजूद नहीं होते हैं, यदि आप अपनी तालिका के लिए स्कीमा पोस्ट कर सकते हैं तो यह दिलचस्प होगा। यह इस प्रकार से दिखाई दे सकता है का एक उदाहरण है

UserKey UserBusinessKey State ValidFrom ValidTo Version Status 
7234  John_Smith_17 Indiana 2005-03-20 2010-06-23 1  expired 
9116  John_Smith_17 Ohio  2010-06-24 3000-01-01 2  current 

(जॉन स्मिथ 2010-06-24 पर इंडियाना से ओहियो में ले जाया गया) एक पंक्ति के नवीनतम संस्करण को प्राप्त करने के लिए इसका इस्तेमाल करने के लिए आम है

WHERE Status = 'current' 

या

WHERE ValidTo = '3000-01-01' 

नोट यह एक दूर भविष्य में किसी स्थिर है।

या

WHERE ValidTo > CURRENT_DATE 

लगता है कि आपके उदाहरण ValidFrom (EFFECTIVE_DATE) का उपयोग करता है, तो आप नवीनतम पंक्ति का पता लगाने का में max() लगाने के लिए मजबूर हैं। स्कीमा पर एक नज़र डालें - क्या आपकी टेबल में Status or ValidTo समकक्ष हैं?

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