建议将 Oracle PL/SQL 函数声明为PARALLEL_ENABLE
可以并行化,以便 DBMS 知道它可以并行运行该函数。
但是函数什么时候可以并行化呢?或者更确切地说:什么时候不是?
让我们看一个例子:
CREATE OR REPLACE FUNCTION get_country_name(p_country_code VARCHAR2) RETURN VARCHAR2
PARALLEL_ENABLE
AS
PRAGMA UDF;
v_country_name country.name%TYPE;
BEGIN
SELECT name INTO v_country_name
FROM country
WHERE code = p_country_code;
RETURN v_country_name;
EXCEPTION WHEN OTHERS THEN
RETURN NULL;
END;
该函数选择给定国家/地区代码的国家/地区名称,例如“法国”代表“FR”。我将其设为 UDF,因为我将主要在 SQL 查询中使用它,并且我将其设为并行启用,因为,那么它可以更好地工作select /*+parallel(4)*/ get_country_name(code) from ...
- 这就是它的意思吗?或者还有什么?
为什么我可以声明这个函数PARALLEL_ENABLE
?到底是什么让它可以并行化?我可以声明我的所有功能PARALLEL_ENABLE
吗?那我就应该这样,不是吗?或者有什么情况会阻止这种情况发生?什么会阻止函数并行化?
PARALLEL_ENABLE
有点神秘。Oracle的文档很不清楚。可以肯定的是,您在并行查询(PQ,块的并行化)中不需要它SELECT
- 并行从站将愉快地执行子句中的标量函数,SELECT
而不会被标记为PARALLEL_ENABLE
.它确实产生影响的一个地方是使用非纯函数时的并行 DML (pdml) 。根据文档:
实际上,只有当函数是非纯函数时才需要这个,而当函数是常规 PQ 时则根本不需要。这是一个演示,任意使用我命名为“快照”的大表。
这会串行执行函数调用并有效地禁用 pdml 工作:
执行计划:
如您所见,
LOAD AS SELECT
操作位于上方/之后PX COORDINATOR
,因此没有 PDML。实际的插入步骤是序列化的。计划评论甚至给我们提供了一个例子来说明原因。当然这是有道理的:根据哪个 PX 从机执行它,结果会有所不同(因为我返回了执行进程的 SID)。Oracle 不希望我们根据是否涉及 PX 或行的分布方式得到不同的结果,但这会导致这种情况。所以,我们必须在坟墓上发誓,这确实是我们想要的。现在添加
PARALLEL_ENABLE
:执行计划:
现在
LOAD AS SELECT
位于下方/之前PX COORDINATOR
,因此我们在这里处于完整的 PDML 模式,并且插入速度会快得多。添加PARALLEL_ENABLE
到该标量函数使得可以在 PDML 操作中使用它。如果函数是pure,则
PARALLEL_ENABLE
不需要该子句。没有它,PDML 也能正常工作,因为 Oracle 知道无论行如何分布,结果都不会改变:计划:
仍处于 PDML 模式,但没有
PARALLEL_ENABLE
.它还有其他用途。文档将其与管道函数(特别是引用游标)结合讨论,但我从未明确看到它的工作原理。我通常将其添加到我的管道函数中,但我的执行总是显示序列化输出,然后将其分发到第一个 PX 从属集。我从未见过输出本身并行化。
也许其他人可以在这里投入他们的经验,他们已经成功地使其与管道表函数一起工作。
PARALLEL_ENABLE
曾经更重要,并且是任何类型的并行操作所必需的。目前的影响要小得多,保罗的回答很好地描述了这些影响。根据11.2 数据库 PL/SQL 语言参考,
PARALLEL_ENABLE
需要允许该函数并行运行:12.2数据库PL/SQL 语言参考现在解释该子句主要适用于 DML 操作。我认为下面引用的最后一句话是一个文档错误;作者添加了第一句限制该条款的范围,但忘记修改暗示该条款适用于所有并行操作的原始句子。
我没有用于测试的 11g 实例,但我想我记得必须添加
PARALLEL_ENABLE
许多功能,即使不涉及 DML。根据我的测试,查询中使用的函数在使用或不使用PARALLEL_ENABLE
.