यह वास्तव में एक अच्छा प्रश्न है।
मैंने पहली बार तालिका बनाने और नमूना डेटा सम्मिलित करने का प्रयास किया (केवल पाँच पंक्तियाँ):
create table my_table(value number);
insert into my_table(value) values(1);
insert into my_table(value) values(2);
insert into my_table(value) values(3);
insert into my_table(value) values(4);
insert into my_table(value) values(5);
मैंने इसका परीक्षण करने के लिए एक सरल परीक्षण पैकेज बनाया है।
create or replace package my_package is
g_counter_SELECT PLS_INTEGER := 0; -- counter for SELECT statement
g_counter_WHERE PLS_INTEGER := 0; -- counter for WHERE clause
function my_function(number_in in number, type_in in varchar2) return number;
procedure reset_counter;
end;
/
और शरीर...
create or replace package body my_package is
function my_function(number_in in number, type_in in varchar2) return number is
begin
IF(type_in = 'SELECT') THEN
g_counter_SELECT := g_counter_SELECT + 1;
ELSIF(type_in = 'WHERE') THEN
g_counter_WHERE := g_counter_WHERE + 1;
END IF;
return mod(number_in, 2);
end;
procedure reset_counter is
begin
g_counter_SELECT := 0;
g_counter_WHERE := 0;
end;
end;
/
अब, हम Oracle 9i पर परीक्षण चला सकते हैं (11g पर समान परिणाम हैं):
-- reset counter
exec my_package.reset_counter();
-- run query
select t.value, my_package.my_function(t.value, 'SELECT')
from my_table t
where my_package.my_function(t.value, 'WHERE') = 1;
-- print result
exec dbms_output.put_line('Count (SELECT) = ' || my_package.g_counter_SELECT);
exec dbms_output.put_line('Count (WHERE) = ' || my_package.g_counter_WHERE);
परिणाम है:
DBMS Output (Session: [1] [email protected] at: 08.09.2010 01:50:04):
-----------------------------------------------------------------------
Count (SELECT) = 3
Count (WHERE) = 5
यहाँ योजना तालिका है:
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | TABLE ACCESS FULL | MY_TABLE | | | |
--------------------------------------------------------------------
जिसका अर्थ है कि तालिका की प्रत्येक पंक्ति (पूर्ण तालिका स्कैन के मामले में) के लिए फ़ंक्शन (WHERE calues में) कहा जाता है। SELECT स्टेटमेंट में जितनी बार शर्त का अनुपालन किया जाता है उतनी ही बार लॉन्च किया जाता है जहां my_function =1
अब... अपनी दूसरी क्वेरी का परीक्षण करें (Oracle9i और 11g पर समान परिणाम)
परिणाम है:
DBMS Output (Session: [1] [email protected] at: 08.09.2010 02:08:04):
-----------------------------------------------------------------------
Count (SELECT) = 8
Count (WHERE) = 0
प्लेन लुक को इस तरह समझाएं (CHOOSE ऑप्टिमाइज़र मोड के लिए):
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | TABLE ACCESS FULL | MY_TABLE | | | |
--------------------------------------------------------------------
प्रश्न है:गणना क्यों (चयन) =8?
चूंकि ओरेकल पहले सबक्वायरी चलाता है (मेरे मामले में पूर्ण टेबल स्कैन के साथ, यह 5 पंक्तियां है =5 चयन कथन में my_function को कॉल करता है):
select t.value, my_package.my_function(t.value, 'SELECT') func_value from my_table t
और इस दृश्य के लिए (सबक्वेरी दृश्य की तरह है) 3 बार चलाएं (उस स्थिति के कारण जहां subquery.func_value =1) फिर से फ़ंक्शन my_function को कॉल करें।
व्यक्तिगत रूप से WHERE क्लॉज में फ़ंक्शन का उपयोग करने की अनुशंसा नहीं करते हैं, लेकिन मैं मानता हूं कि कभी-कभी यह अपरिहार्य होता है।
जैसा कि इसका सबसे खराब संभव उदाहरण निम्नलिखित द्वारा दर्शाया गया है:
select t.value, my_package.my_function(t.value, 'SELECT')
from my_table t
where my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE')
and my_package.my_function(t.value, 'WHERE') = my_package.my_function(t.value, 'WHERE');
Oracle 9i पर परिणाम कहां है :
Count (SELECT) = 5
Count (WHERE) = 50
और Oracle 11g पर है :
Count (SELECT) = 5
Count (WHERE) = 5
जो इस मामले में दर्शाता है कि कभी-कभी कार्यों का उपयोग प्रदर्शन के लिए महत्वपूर्ण हो सकता है। अन्य मामलों में (11g) यह डेटाबेस को स्वयं हल करता है।