4

我正在创建一个多次使用 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;

当我运行我的代码时,general.column1 将引用 column1 语句中的函数,而不是它返回的数据(这最终是我所追求的)。

我对 SQL 相当陌生,因此感谢您提供任何帮助,如果您需要更多信息,我会尽力提供。

谢谢!

4

2 回答 2

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
于 2013-02-01T08:35:00.680 回答
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如果它是确定性的,那么decaring 函数也很有帮助。

一个小例子:

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,我们可以用它来代替确定性,这会将 subsequant 运行的调用减少到 0 调用。

于 2013-01-31T21:13:36.393 回答