一个SELECT
语句的WHERE
子句中调用函数是一个坏消息。首先,该功能将被称为许多行,其中不是满足查询的条件,因为该功能正在用于执行部分过滤。我曾经有过这看起来有点像
SELECT t.TRANSACTION_ID, t.SOME_OTHER_FIELD
FROM TRANSACTIONS t
WHERE MY_PACKAGE.IS_SALES_TRANSACTION(t.TRANSACTION_CODE) = TRUE AND
X <> Y AND
Y <> Z
和MY_PACKAGE.IS_SALES_TRANSACTION
功能类似于
FUNCTION IS_SALES_TRANSACTION(pTransaction_code IN NUMBER)
RETURNS BOOLEAN IS
BEGIN
IF pTransaction_code IN (10, 11, 12, 13) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END IS_SALES_TRANSACTION;
我的小查询花了约15分钟的运行,这使得任何意义,我因为查询的SELECT语句表中只有约10,000,000个中返回了约5000行。在完成代码的一些工作之后,我发现这个函数被称为几百万次,并占用了15分钟执行时间的大部分时间。将SELECT语句更改为
SELECT t.TRANSACTION_ID, t.SOME_OTHER_FIELD
FROM TRANSACTIONS t
WHERE t.TRANSACTION_CODE IN (10, 11, 12, 13) AND
X <> Y AND
Y <> Z
导致光标在不到一秒内完成。
祝你好运。
从SQL调用的函数只能在插入和删除,如果它使用编译指示自治事务声明,否则它会得到ORA-14551。为什么他们需要一个每次查询都会执行大量工作的视图(这会发生,因为视图只是一个存储查询;可能每行取决于它的引用方式)? –
谢谢@ alex-poole。我知道,这太疯狂了......它已经被定义为一个自治事务,但我正在努力将它们从视图定义中移除并创建一个单独的过程。你知道函数的执行频率如何?每个用户访问该视图是否会受到影响? – user2724502
这取决于它是如何定义和调用的(是确定性的,例如?),但是如果它位于'where子句中,它可能会被每个用户对每个查询的查询多次调用。即使一个用户每天只查看一次视图,它仍然是......不寻常的...至多也可能仍被称为多次。一个单独的过程,可能通过工作调用,更有意义。或者可能是一个程序,检查当天繁重的工作是否已经完成,如果没有,那么通过OUT sys-refcursor返回与视图相同的数据,比如真的依赖。 –