SQL语句中的存储过程并行执行 (Oracle 11g)

3

我有一个SQL语句,其中使用了一个检查函数(Check-Function),执行时间相当长。

现在我想并行执行检查函数(Check-Function),但是它却不起作用。

我犯了什么错误?

以下示例需要5秒才能执行完,但据我理解,由于并行处理,应该只需要1秒左右。

用于测试的代码片段:

CREATE TABLE PERSON AS
SELECT LEVEL AS ID, 'Person_'||LEVEL AS NAME
FROM DUAL 
CONNECT BY LEVEL <= 5;

CREATE OR REPLACE FUNCTION LONGCHECKFUNC(ID NUMBER)
RETURN NUMBER IS
BEGIN
    --Doing some very heavy Checks....
    DBMS_LOCK.SLEEP(1 /*second*/);
    RETURN 1;
END;

SELECT /*+PARALLEL(person, 5) */ *
 FROM PERSON
WHERE LONGCHECKFUNC(ID)=1;

所以您想要一些异步执行过程的方式?同时并行执行多个过程? - Jacob
没错。我想同时为每一行执行相同的过程(LongCheckFunc)。 - bernhard.weingartner
1
看一下这个链接,可能会有用。 - Jacob
2个回答

1
CREATE TABLE PERSON
PARTITION BY HASH(ID) PARTITIONS 16 /* <-- ADDED*/
AS
SELECT LEVEL AS ID, 'Person_'||LEVEL AS NAME
FROM DUAL 
CONNECT BY LEVEL <= 5;

CREATE OR REPLACE FUNCTION LONGCHECKFUNC(ID NUMBER)
RETURN NUMBER PARALLEL_ENABLE /* <-- ADDED*/ IS
BEGIN
    --Doing some very heavy Checks....
    DBMS_LOCK.SLEEP(1 /*second*/);
    RETURN 1;
END;
/

SELECT /*+PARALLEL(person, 5) */ *
 FROM PERSON
WHERE LONGCHECKFUNC(ID)=1;

首先,您需要在函数中添加PARALLEL_ENABLE。这告诉Oracle函数调用不共享任何会话数据,并且可以独立运行。

第二个更改,添加哈希分区,我不完全理解。这取决于Oracle用于划分工作负载的内部算法。当存在哈希分区时,最简单的方法可能是将段分配给并行服务器。如果没有分区,则只有少量块,Oracle可能认为在单个并行服务器上运行所有内容最快。

(即使您使用ASSOCIATE STATISTICS并赋予函数荒谬的成本,Oracle仍将以串行方式运行它。也许存在某些限制,Oracle永远不会将块分割为多个并行服务器?)

在我的机器上,这个程序运行大约需要1.1秒。但由于它依赖于(据我所知)未记录的行为,我不确定它是否会在您的机器上运行相同。Oracle的哈希函数不会简单地将值放入桶中,以轮流方式进行。为了最小化冲突并增加最佳并行性的机会,您需要使用大量分区。

正如@David Aldridge所提到的,并行查询实际上并不是为此而设计的。如果您想要更确定性的过程,您需要像@Polppan建议的解决方案一样使用DBMS_SCHEDULER。


非常感谢,这正是我想要的解决方案。它完美地为我工作! - bernhard.weingartner

1

并行查询不适用于此类尝试的功能。

在这里最好的做法是从调整函数本身开始。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接