sql - SQL语句中过程的并行执行(Oracle 11g)

标签 sql plsql oracle11g optimizer-hints

我有一个使用 Check-Function 的 SQL 语句,它需要很长时间才能执行。

现在我想并行化 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;

最佳答案

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,函数调用不共享任何 session 数据,并且可以独立运行。

第二个变化,加入hash分区,我不是很懂。这取决于 Oracle 用于划分工作负载的内部算法。当存在散列分区时,在并行服务器之间划分段可能是最简单的。没有分区,只有少量 block ,Oracle 可能认为在单个并行服务器上运行所有内容是最快的。

(即使您使用 ASSOCIATE STATISTICS 并为该函数提供可笑的成本,Oracle 仍会串行运行它。也许存在一些限制,Oracle 永远不会在多个并行服务器之间拆分一个 block ?)

这在大约 1.1 中运行。在我的机器上秒。但是由于它取决于(AFAIK)未记录的行为,我不确定它是否会为您运行相同的行为。 Oracle 的散列函数不会以简单的循环方式将值放入桶中。为了最大限度地减少冲突并增加最佳并行性的机会,您将需要使用大量分区。

正如@David Aldridge 提到的,并行查询并不是真正为此设计的。如果您想要一个更具确定性的过程,您将需要类似于@Polppan 建议的解决方案(使用 DBMS_SCHEDULER)。

关于sql - SQL语句中过程的并行执行(Oracle 11g),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13451944/

相关文章:

sql - Oracle - 计算 CASE 语句的结果

sql - 具有特定逻辑的 Oracle row_number/rank

sql查询中的python列表作为参数

MYSQL - 一列引用多表

mysql - 尝试使用 'insert into select' 查询时获取列不能为空

sql - Oracle:有没有办法使用 unix crypt 方法对值进行编码?

java - 多个 XML 文件验证的自动化

sql - oracle中如何将数字转换为日期时间

oracle - PL/SQL 上的 get_detailed_sqlerrm 语法

sql - 仅将带有年份和月份的字符串...转换为仅限年份和月份的日期格式