我正在创建一个多次使用2个嵌入式服务器功能的查询。
问题:函数搜索一个相当大的表,它们需要很长时间才能执行。
目标:使用子查询就像它是一个表一样,这样我就可以引用列而不运行该函数来多次生成列。
Example Pseudocode:
Select general.column1, general.column2, general.column1-general.column2
from (select package.function1('I take a long time') column1,
package.function2('I take even longer') column2,
normal_column
from bigtable) general;
Select general.column1, general.column2, general.column1-general.column2
from (select package.function1('I take a long time') column1,
package.function2('I take even longer') column2,
normal_column
from bigtable) general;
当我运行我的代码时,general.column1将引用column1语句中的函数,而不是它返回的数据(这最终是我所追求的)。
我对SQL很新,所以感谢任何帮助,如果您需要更多信息,我会尽力提供。
谢谢!
答案 0 :(得分:5)
我建议你使用子查询因子。第一个子查询只执行一次,然后用于查询的其余部分。
WITH function_result AS
(SELECT package.function1('I take a long time') column1
, package.function2('I take even longer') column2
FROM dual)
SELECT function_result.column1
, function_result.column2
, function_result.column1 - function_result.column2
, bigtable.normal_column
FROM bigtable
答案 1 :(得分:4)
一般来说,你想要做的是在这种情况下采取标量子查询缓存的优点。
即。放:
Select general.column1, general.column2, general.column1-general.column2
from (select (select package.function1('I take a long time') from dual) column1,
(select package.function2('I take even longer') from dual) column2,
normal_column
from bigtable) general;
如果它是确定性的,那么将函数描述为deterministic
也会有所帮助。
一个小例子:
SQL> create or replace function testfunc(i varchar2)
2 return varchar2
3 is
4 begin
5 dbms_application_info.set_client_info(userenv('client_info')+1 );
6 return 'hi';
7 end;
8 /
Function created.
现在让我们像你一样测试对函数的调用:
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> set autotrace traceonly
SQL> select *
2 from (select testfunc(owner) a
3 from all_objects);
57954 rows selected.
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
----------------------------------------------------------------
57954
该函数被称为57954次(每行一次)。现在让我们使用标量缓存:
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> select *
2 from (select (select testfunc(owner) from dual) a
3 from all_objects);
57954 rows selected.
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
----------------------------------------------------------------
178
178次来电而不是57k! 在你的情况下,你只显示你有一个文字,没有每行变化的输入(如果是这种情况,使用标量缓存后的调用次数应为1)。
如果我们添加确定性:
SQL> create or replace function testfunc(i varchar2)
2 return varchar2 deterministic
3 is
4 begin
5 dbms_application_info.set_client_info(userenv('client_info')+1 );
6 return 'hi';
7 end;
8 /
Function created.
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> select *
2 from (select (select testfunc(owner) from dual) a
3 from all_objects);
57954 rows selected.
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
----------------------------------------------------------------
55
现在降到55.在11g中我们有result_cache
我们可以用它来代替确定性,这会减少对子序列运行的调用到0次调用。