पहले दूसरे प्रश्न का उत्तर दें:
<ब्लॉकक्वॉट>"जीटीटी से दूर क्यों जाएं? क्या वे वाकई इतने बुरे हैं।"
कुछ दिनों पहले मैं अवधारणा का एक सबूत दस्तक दे रहा था जिसने एक बड़ी एक्सएमएल फ़ाइल (~ 18 एमबी) को एक्सएमएल टाइप में लोड किया था। क्योंकि मैं XMLType को स्थायी रूप से संग्रहीत नहीं करना चाहता था, इसलिए मैंने इसे PL/SQL चर (सत्र स्मृति) और एक अस्थायी तालिका में लोड करने का प्रयास किया। इसे एक अस्थायी तालिका में लोड करने में इसे XMLType चर में लोड करने में पांच गुना समय लगता है (एक सेकंड की तुलना में 5 सेकंड)। अंतर इसलिए है क्योंकि अस्थायी टेबल मेमोरी स्ट्रक्चर नहीं हैं:वे डिस्क पर लिखे जाते हैं (विशेष रूप से आपके नामांकित अस्थायी टेबलस्पेस)।
यदि आप बहुत सारे डेटा को कैश करना चाहते हैं तो इसे मेमोरी में स्टोर करना पीजीए पर जोर देगा, जो कि बहुत सारे सत्र होने पर अच्छा नहीं है। तो यह RAM और समय के बीच का समझौता है।
पहले प्रश्न के लिए:
<ब्लॉकक्वॉट>"क्या कोई उपरोक्त नमूना प्रश्नों को संग्रह और/या कर्सर में बदलने का तरीका दिखा सकता है?"
आपके द्वारा पोस्ट की जाने वाली क्वेरीज़ को एक स्टेटमेंट में मर्ज किया जा सकता है:
SELECT case when a.column_a IS NULL OR a.column_a = ' '
then b.data_a
else column_a end AS someA,
a.someB,
a.someC
FROM TABLE_A a
left outer join TABLE_B b
on ( a.column_b = b.data_b AND a.column_c = 'C' )
WHERE condition_1 = 'YN756'
AND type_cd = 'P'
AND TO_NUMBER(TO_CHAR(m_date, 'MM')) = '12'
AND (lname LIKE (v_LnameUpper || '%') OR
lname LIKE (v_searchLnameLower || '%'))
AND (e_flag = 'Y' OR
it_flag = 'Y' OR
fit_flag = 'Y'));
(मैंने बस आपके तर्क को स्थानांतरित कर दिया है लेकिन वह case()
स्टेटमेंट को एक बेहतर nvl2(trim(a.column_a), a.column_a, b.data_a)
से बदला जा सकता है )।
मुझे पता है कि आप कहते हैं कि आपके प्रश्न अधिक जटिल हैं लेकिन कॉल का आपका पहला पोर्ट उन्हें फिर से लिखने पर विचार करना चाहिए। मुझे पता है कि पीएल/एसक्यूएल के साथ सिले हुए बहुत सारे बेबी एसक्यूएल में एक गंभीर क्वेरी को तोड़ना कितना मोहक है, लेकिन शुद्ध एसक्यूएल अधिक कुशल है।
संग्रह का उपयोग करने के लिए SQL में प्रकारों को परिभाषित करना सबसे अच्छा है, क्योंकि यह हमें SQL कथनों के साथ-साथ PL/SQL में उनका उपयोग करने की सुविधा देता है।
create or replace type tab_a_row as object
(col_a number
, col_b varchar2(23)
, col_c date);
/
create or replace type tab_a_nt as table of tab_a_row;
/
यहां एक नमूना फ़ंक्शन है, जो एक परिणाम सेट देता है:
create or replace function get_table_a
(p_arg in number)
return sys_refcursor
is
tab_a_recs tab_a_nt;
rv sys_refcursor;
begin
select tab_a_row(col_a, col_b, col_c)
bulk collect into tab_a_recs
from table_a
where col_a = p_arg;
for i in tab_a_recs.first()..tab_a_recs.last()
loop
if tab_a_recs(i).col_b is null
then
tab_a_recs(i).col_b := 'something';
end if;
end loop;
open rv for select * from table(tab_a_recs);
return rv;
end;
/
और यहाँ यह क्रिया में है:
SQL> select * from table_a
2 /
COL_A COL_B COL_C
---------- ----------------------- ---------
1 whatever 13-JUN-10
1 12-JUN-10
SQL> var rc refcursor
SQL> exec :rc := get_table_a(1)
PL/SQL procedure successfully completed.
SQL> print rc
COL_A COL_B COL_C
---------- ----------------------- ---------
1 whatever 13-JUN-10
1 something 12-JUN-10
SQL>
फ़ंक्शन में ORA-00947 अपवाद से बचने के लिए कॉलम के साथ टाइप को इंस्टेंट करना आवश्यक है। PL/SQL तालिका प्रकार को पॉप्युलेट करते समय यह आवश्यक नहीं है:
SQL> create or replace procedure pop_table_a
2 (p_arg in number)
3 is
4 type table_a_nt is table of table_a%rowtype;
5 tab_a_recs table_a_nt;
6 begin
7 select *
8 bulk collect into tab_a_recs
9 from table_a
10 where col_a = p_arg;
11 end;
12 /
Procedure created.
SQL>
आखिरकार, दिशानिर्देश
<ब्लॉकक्वॉट>"कब का उपयोग करें और GTT से कब बचें इसके बारे में दिशानिर्देश क्या होने चाहिए"
जब हमें एक ही सत्र में विभिन्न प्रोग्राम इकाइयों के बीच कैश्ड डेटा साझा करने की आवश्यकता होती है, तो वैश्विक अस्थायी तालिकाएँ बहुत अच्छी होती हैं। उदाहरण के लिए यदि हमारे पास एक जीटीटी को खिलाने वाले एकल फ़ंक्शन द्वारा उत्पन्न एक सामान्य रिपोर्ट संरचना है जो कई प्रक्रियाओं में से एक द्वारा पॉप्युलेट की जाती है। (यद्यपि वह भी गतिशील रेफ कर्सर के साथ लागू किया जा सकता है ...)
वैश्विक अस्थायी तालिकाएँ भी अच्छी हैं यदि हमारे पास बहुत अधिक मध्यवर्ती प्रसंस्करण है जो कि एक एकल SQL क्वेरी के साथ हल करने के लिए बहुत जटिल है। विशेष रूप से यदि उस प्रसंस्करण को पुनर्प्राप्त पंक्तियों के सबसेट पर लागू किया जाना चाहिए।
लेकिन सामान्य तौर पर यह अनुमान होना चाहिए कि हमें अस्थायी तालिका का उपयोग करने की आवश्यकता नहीं है। तो
- इसे SQL में तब तक करें जब तक कि यह बहुत कठिन न हो, जो भी मामला हो ...
- ... इसे पीएल/एसक्यूएल वेरिएबल्स (आमतौर पर संग्रह) में करें जब तक कि इसमें बहुत अधिक मेमोरी न हो जो भी मामला हो ...
- ... इसे वैश्विक अस्थायी तालिका के साथ करें