2016-01-13 50 views
0

我们有一位客户在Oracle中创建了一个视图效果不佳的客户,并且查看视图的SQL显示他们正在视图定义的WHERE子句中使用函数调用。这个功能相当密集,包括DELETEs和INSERTs。Oracle视图在WHERE子句中使用函数...什么性能影响?

我的直觉是,这不是一个好主意,但我不知道如何表达确切的原因......?

每次有人查询视图时,函数都会执行吗?

每天刷新(例如)的物化视图会更有意义,因此该函数每天只执行一次? (我想这将取决于被爆炸了所需的数据是否迄今为止所有的时间...?)

感谢

+1

从SQL调用的函数只能在插入和删除,如果它使用编译指示自治事务声明,否则它会得到ORA-14551。为什么他们需要一个每次查询都会执行大量工作的视图(这会发生,因为视图只是一个存储查询;可能每行取决于它的引用方式)? –

+0

谢谢@ alex-poole。我知道,这太疯狂了......它已经被定义为一个自治事务,但我正在努力将它们从视图定义中移除并创建一个单独的过程。你知道函数的执行频率如何?每个用户访问该视图是否会受到影响? – user2724502

+0

这取决于它是如何定义和调用的(是确定性的,例如?),但是如果它位于'where子句中,它可能会被每个用户对每个查询的查询多次调用。即使一个用户每天只查看一次视图,它仍然是......不寻常的...至多也可能仍被称为多次。一个单独的过程,可能通过工作调用,更有意义。或者可能是一个程序,检查当天繁重的工作是否已经完成,如果没有,那么通过OUT sys-refcursor返回与视图相同的数据,比如真的依赖。 –

回答

2

一个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 

导致光标在不到一秒内完成。

祝你好运。

相关问题