Oracle SQL:如果我将一个函数既作为字段又按顺序使用,是否会再次进行评估?

Gui*_*ens 6 sql oracle performance plsql oracle11g

假设您有一个PL/SQL函数返回一些随机值,您将在SQL sentence返回的数据和Order by子句中使用它们.

现在,您可以用Order by三种"不同"的方式编写该子句:

按索引

Select Foo,
       MyFunction(Foo) orderField
  From FooTable
 Order By 2
Run Code Online (Sandbox Code Playgroud)

通过调用"再次"功能

Select Foo,
       MyFunction(Foo) orderField
  From FooTable
 Order By MyFunction(Foo)
Run Code Online (Sandbox Code Playgroud)

通过使用订单字段别名

Select Foo,
       MyFunction(Foo) orderField
  From FooTable
 Order By orderField
Run Code Online (Sandbox Code Playgroud)

第三种方法是可能的,因为该Order By子句是要解析的select的最后一个,然后Oracle已经知道了别名.

我的问题是,这三个查询的处理或性能有什么不同吗?特别是,第二个是否意味着MyFunction将再次评估呼叫?

我试图通过搜索文档,并通过运行Toad的一些查询以及查看explain plan但直到现在找不到任何显着差异来找出答案.

我的Oracle版本是11.2.0.3.0,如果这有任何问题.

Dmi*_*riy 7

在这种情况下检查发生了什么的好方法是使用序列(但我有oracle版本12.1).例如:

SQL> create sequence func_seq;

Sequence created.

SQL> create or replace function foo return number is
begin
  return func_seq.nextval;
end;
/

Function created.
Run Code Online (Sandbox Code Playgroud)

首先,创建一个返回两行(没有ORDER BY子句)的查询并检查序列的值:

SQL> select foo from dual connect by level <= 2;

       FOO
----------
         1
         2

SQL> select func_seq.currval from dual;

   CURRVAL
----------
         2
Run Code Online (Sandbox Code Playgroud)

然后查询ORDER BY:

SQL> select foo from dual connect by level <= 2 order by foo;

       FOO
----------
         3
         4

SQL> select func_seq.currval from dual;

   CURRVAL
----------
         4
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,功能执行了2次.
但是如果你的函数需要参数,你必须注意它们的值:

SQL> create or replace function foo(p number) return number is
begin
  return func_seq.nextval;
end;
/  

Function created.
Run Code Online (Sandbox Code Playgroud)

使用不同的参数进行查询:

SQL> select foo(1) from dual connect by level <= 2 order by foo(2);

    FOO(1)
----------
         6
         8

SQL> select func_seq.currval from dual;

   CURRVAL
----------
         8
Run Code Online (Sandbox Code Playgroud)

我们可以看到,函数执行了4次.