首页 > 解决方案 > sql查询中函数的执行顺序是什么?

问题描述

如果我构建自己的函数“myfunction”和这个查询:

select
myfunction(parameters)
from
mytable
where
a and b and c and d

如果 mytable 有 100 万行,但在我的 where 我只有 100 行之后。当我执行了这个查询时,myfunction 会执行 100 行还是 100 万行?

在这种情况下会发生什么?

select
myfunction(parameters)
from
mytable
where
a and b and c and d and myfunction(parameters) == e

标签: sqloracle

解决方案


在第一个示例中,它只会执行 100 次。您可以通过在函数中添加调试调用来验证这一点:

create table mytable (a, b) as select mod(level, 10), level from dual connect by level <= 50;

create or replace function myfunction(p number)
return number as
begin
  dbms_output.put_line('In function for p=' || p);
  return mod(p,3);
end;
/

set serveroutput on

select myfunction(b)
from mytable
where a = 1;

MYFUNCTION(B)
-------------
            1
            2
            0
            1
            2

In function for p=1
In function for p=11
In function for p=21
In function for p=31
In function for p=41

where仅对匹配子句过滤器的行调用该函数。但是,据我所知,这并不能保证。

在第二个示例中它相当复杂,并且很大程度上取决于优化器。对于我的简单演示,优化器(在本例中为 11gR2)首先评估a,并且只为匹配的行调用函数;但它随后再次为选择列表值调用它:

select myfunction(b)
from mytable
where a = 1
and myfunction(b) = 2;

MYFUNCTION(B)
-------------
            2
            2

In function for p=1
In function for p=11
In function for p=11
In function for p=21
In function for p=31
In function for p=41
In function for p=41

a=1与以前一样,为五行中的每一行调用该函数,对于myfunction(b) = 2第二次调用该函数的行,以获取结果集中的值。

同样,对于这个例子,你可能认为会改变这种行为的事情不会。所有这些都得到完全相同的输出:

select myfunction(b)
from mytable
where myfunction(b) = 2
and a = 1;

select x
from (
  select myfunction(b) as x
  from mytable
  where a = 1
)
where x = 2;

select x
from (
  select /*+ materialize */ myfunction(b) as x
  from mytable
  where a = 1
)
where x = 2;

with t (x) as (
  select myfunction(b)
  from mytable
  where a = 1
)
select x
from t
where x = 2;

优化器在内部将它们全部重写到同一个查询中,您仍然可以获得所有七个函数调用。添加一个未记录的提示确实会改变它:

with t (x) as (
  select /*+ materialize */ myfunction(b)
  from mytable
  where a = 1
)
select x
from t
where x = 2;

         X
----------
         2
         2

In function for p=1
In function for p=11
In function for p=21
In function for p=31
In function for p=41

但是您不能(或不应该)真正使用或依赖它。

索引、分区、优化器版本、统计信息等都会影响优化器对查询的行为方式

和其他要考虑的事情一样,你可以有一个基于函数的索引,或者一个确定性的函数......

所以……这取决于。


推荐阅读