【发布时间】:2015-07-27 17:19:51
【问题描述】:
Oracle 是否可以在不使用函数结果缓存的情况下,在同一个查询(事务?)中调用函数的结果时重用它的结果?
我正在使用的应用程序严重依赖 Oracle 函数。许多查询最终会多次执行完全相同的函数。
一个典型的例子是:
SELECT my_package.my_function(my_id),
my_package.my_function(my_id) / 24,
my_package.function_also_calling_my_function(my_id)
FROM my_table
WHERE my_table.id = my_id;
我注意到 Oracle 总是执行这些函数中的每一个,而没有意识到同一函数在一秒钟前在同一个查询中被调用。函数中的某些元素可能会被缓存,从而导致返回速度稍快。这与我的问题无关,因为我想避免整个第二次或第三次执行。
假设这些函数相当消耗资源,并且这些函数可能会调用更多函数,它们的结果基于相当大且更新频繁的表(一百万条记录,每小时更新 1000 次)。因此无法使用 Oracle 的函数结果缓存。
即使数据经常变化,我希望这些函数在从同一个查询中调用时的结果是相同的。
Oracle 是否可以重用这些函数的结果以及如何重用?我正在使用 Oracle11g 和 Oracle12c。
下面是一个例子(只是一个随机的无意义函数来说明问题):
-- Takes 200 ms
SELECT test_package.testSpeed('STANDARD', 'REGEXP_COUNT')
FROM dual;
-- Takes 400ms
SELECT test_package.testSpeed('STANDARD', 'REGEXP_COUNT')
, test_package.testSpeed('STANDARD', 'REGEXP_COUNT')
FROM dual;
用到的函数:
CREATE OR REPLACE PACKAGE test_package IS
FUNCTION testSpeed (p_package_name VARCHAR2, p_object_name VARCHAR2)
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY test_package IS
FUNCTION testSpeed (p_package_name VARCHAR2, p_object_name VARCHAR2)
RETURN NUMBER
IS
ln_total NUMBER;
BEGIN
SELECT SUM(position) INTO ln_total
FROM all_arguments
WHERE package_name = 'STANDARD'
AND object_name = 'REGEXP_COUNT';
RETURN ln_total;
END testSpeed;
END;
/
【问题讨论】:
-
您仍然可以使用结果缓存和“relies_on”关键字来处理表更改 - oracle.com/technetwork/issue-archive/2010/10-sep/… 为什么不使用 WITH 子句调用该函数一次,然后在查询中引用该结果?
-
在 12c 中,您可以在 SQL 语句中声明函数,这与 PL/SQL 非常不同(从事务的角度来看)
-
使用 WITH 子句并没有帮助,因为不幸的是它仍然执行了两次函数。我看不到 RELIES_ON 关键字如何改变任何东西,在 11gR2 中,依赖关系被自动识别,并且表多次获取数据更改,从而使缓存无效。我正在专门寻找在同一个查询中的缓存。 12c WITH FUNCTION 子句很有趣,我可以在这里和那里应用它,但它并不能解决更大的问题,尽管当具有嵌套函数的函数非常复杂并利用我正在使用的应用程序框架时。
-
问题真的来自为 1 个特定 id 调用函数几次,或者当您尝试选择多行时(从 my_table 中选择 my_function(id),其中 id 介于 1 和 100000 之间)?您描述的情况将导致对该函数的少量调用,而我描述的第二种情况要糟糕得多。但是有一个技巧可能适用于第二种情况
标签: sql oracle performance function