Oracle 是否有类似于DETERMINISTIC的PL/SQL杂注,但仅限于一个SQL SELECT的范围?
在SQLOracle 是否有类似于DETERMINISTIC的PL/SQL杂注,但仅限于一个SQL SELECT的范围?,oracle,optimization,plsql,stored-functions,deterministic,Oracle,Optimization,Plsql,Stored Functions,Deterministic,在SQLSELECT语句中,我想执行一个函数,该函数对于该SELECT语句的范围是确定的(或者事务也可以): t.x的许多值都是相同的,因此Oracle可以省略一次又一次调用相同的函数,以加快速度。但是如果我将函数标记为DETERMINISTIC,则结果可能会在多次执行此查询之间缓存。我不能使用确定性的原因是my_函数使用了一个不时更改的配置参数 还有其他关键字我可以用吗?是否有我应该注意的问题(内存问题、并发性等)?或者任何其他技巧,例如分析函数,每个t.x值只调用函数一次(无重大性能影响)?
SELECT
语句中,我想执行一个函数,该函数对于该SELECT
语句的范围是确定的(或者事务也可以):
t.x
的许多值都是相同的,因此Oracle可以省略一次又一次调用相同的函数,以加快速度。但是如果我将函数标记为DETERMINISTIC
,则结果可能会在多次执行此查询之间缓存。我不能使用确定性
的原因是my_函数
使用了一个不时更改的配置参数
还有其他关键字我可以用吗?是否有我应该注意的问题(内存问题、并发性等)?或者任何其他技巧,例如分析函数,每个
t.x
值只调用函数一次(无重大性能影响)?一个可能的简单解决方法是创建第二个确定性函数,调用第一个函数;但是,让第二个函数获取一个附加的、无意义的参数,在使用该函数的每个查询中为其提供不同的文本值。这不是对您的问题的回答,但可以为您提供一个解决方案。
您提到的此配置参数不能作为参数添加到函数中?
在这种情况下,my_函数(t.x,val1)
与my_函数(t.x,val2)
是不同的,如果您这样做:
select t.x, t.y, (select my_function(t.x) from dual)
from t
然后Oracle可以使用它来减少函数调用。另一种方法是将函数放入包中,并将结果设置为全局变量。然后,在调用函数时,检查输入变量是否与之前相同,如果相同,则快速返回全局变量:
SQL> create or replace package temp is
2
3 function blah ( PIndex integer ) return integer;
4
5 end temp;
6 /
Package created.
SQL>
SQL> create or replace package body temp is
2
3 GResult integer := 0;
4 GIndex integer;
5
6 function blah ( PIndex integer ) return integer is
7
8 begin
9
10 if Gindex = Pindex then
11 return Gresult;
12 else
13 GIndex := Pindex;
14 GResult := Pindex;
15 end if;
16
17 return Gresult;
18
19 end blah;
20
21 end temp;
22 /
Package body created.
SQL>
SQL> select temp.blah(1) from dual;
TEMP.BLAH(1)
------------
1
SQL>
SQL> select temp.blah(1) from dual;
TEMP.BLAH(1)
------------
1
SQL>
SQL> select temp.blah(2) from dual;
TEMP.BLAH(2)
------------
2
SQL>
好主意!那把戏会奏效的!因此,我将调用
确定性我的\u函数\u 2(t.x,sysdate)
听起来这不会增加项目的可维护性。@ammoQ:是的,原则上你是对的。但这是一个非常远程的脱机作业,而不是非常核心的功能。但是它在数据库上产生了太多的负载。“我可以稍微调整一下……”戴夫·科斯塔,我已经改变了接受的答案。有一篇关于标量子查询缓存的非常有趣的文章!非常好,根据Tom的解释,这似乎比将函数标记为<代码>确定性
更有效。结果缓存
可能符合我的要求,但标量子查询缓存似乎更直观、更直接,甚至更快!回答得好,但实际上我觉得有点令人不安。一些看起来纯粹是语法变化的东西可能会改变查询结果(假设函数是非确定性的)。@Dave Costa,是的,这些东西在Oracle中不断变化。另见我最近问的。在SQL
和PL/SQL
的界面上需要大量的隐式知识,不幸的是,全局变量的寿命可能比两次更改配置值之间的时间长。所以这可能会产生错误的结果…@Lukas,你最了解自己的数据:-)。我从来没有看到过它对我产生不正确的结果,但是我们没有任何执行时间对结果很重要的地方。尽管如此,这仍然是一个好主意。但是,请查看公认的答案。标量子查询缓存是最佳解决方案我不确定在这种情况下我是否会信任Tom。我使用全局缓存动态数组结果。因此,第一个调用将部分填充数组,但随后拥有所需的所有信息将返回正确的值。第三个调用可能会发现它需要更多的信息来完成计算。它将向数组中添加更多的信息-通常计算在内存中完成-然后返回等。我认为Tom的示例实际上是关于“半确定性”函数的,这些函数不是形式确定性的,但不需要对每个结果集行执行-就像我的问题一样。。。
SQL> create or replace package temp is
2
3 function blah ( PIndex integer ) return integer;
4
5 end temp;
6 /
Package created.
SQL>
SQL> create or replace package body temp is
2
3 GResult integer := 0;
4 GIndex integer;
5
6 function blah ( PIndex integer ) return integer is
7
8 begin
9
10 if Gindex = Pindex then
11 return Gresult;
12 else
13 GIndex := Pindex;
14 GResult := Pindex;
15 end if;
16
17 return Gresult;
18
19 end blah;
20
21 end temp;
22 /
Package body created.
SQL>
SQL> select temp.blah(1) from dual;
TEMP.BLAH(1)
------------
1
SQL>
SQL> select temp.blah(1) from dual;
TEMP.BLAH(1)
------------
1
SQL>
SQL> select temp.blah(2) from dual;
TEMP.BLAH(2)
------------
2
SQL>