为什么并行提示在 oracle 19c 中不起作用
Why the parallel hint is not working in oracle 19c
SELECT /*+PARALLEL 8*/
A.ACC_ID,
COALESCE (B.PR_ID, NULL),
COALESCE (B.DESC, NULL),
COALESCE (B.CNT, 0)
FROM (SELECT ACC_ID
FROM ACC_ID_IN
WHERE XXX = 1 AND YYY = 'ABCD') A
LEFT OUTER JOIN
( SELECT /*+PARALLEL 8*/
A.ACC_ID,
B.PR_ID,
B.DESC,
COUNT (DISTINCT A.ACC_NBR) CNT
FROM DB1.TABLE1 A,
TABLE2 B,
TABLE3 C
WHERE A.ACC_ID IN (8888888888)
AND A.P_ID = B.P_ID
AND A.P_ID = C.P_ID
AND A.START <=TO_DATE (SUBSTR (A.ACC_ID, 1, 4) || '1231','YYYY/MM/DD')
AND A.END > TO_DATE (SUBSTR (A.ACC_ID, 1, 4) || '1230','YYYY/MM/DD')
GROUP BY A.ACC_ID, B.PR_ID, B.DESC
ORDER BY A.ACC_ID, B.PR_ID, B.DESC) B
ON A.ACC_ID = B.ACC_ID
WHERE A.ACC_ID IN (8888888888)
GROUP BY A.ACC_ID,
COALESCE (B.PR_ID, NULL),
COALESCE (B.DESC, NULL),
COALESCE (B.CNT, 0)
上面的带有并行提示的查询需要很长时间才能执行,而当我删除并行提示时相同的查询在几秒钟内执行。当 oracle 升级到 19c 时出现此问题。您能否帮助我了解这里发生了什么,我是否需要执行任何设置以启用并行提示作为数据库升级的一部分 activity。
并行性很棘手,并行度可能出乎意料的原因有很多。以下是您的查询的潜在问题,其中一些在评论中提到:
这么快的查询你还想要并行吗?并行更努力,而不是更聪明,所以你通常只想在大对象上使用它需要很长时间来处理。如果查询在没有并行性的情况下在几秒钟内运行,那么它可能首先不是并行性的好候选者。
语句级提示 查询顶部的 /*+ PARALLEL */
提示适用于整个语句,因此您不需要也向其他查询块添加提示。
提示格式不正确 如果要指定并行度,需要在数字两边使用括号,如/*+ PARALLEL(8) */
。如果没有括号,Oracle 将计算并行度。我什至不记得所有的规则和细节,但如果你要求 Oracle 为你生成 DOP,它通常会使用 CPU_COUNT * PARALLEL_THREADS_PER_CPU * NUMBER_OF_INSTANCES
.
CPU_COUNT 由于您刚刚升级,请检查 CPU_COUNT
是否已更改。在某些平台上,例如 Solaris,Oracle 将每个虚拟处理器计算为 CPU,然后仍将其乘以 PARALLEL_THREADS_PER_CPU
,这可能会导致荒谬的数字。虽然那个参数看起来像是你不会碰的东西,但我已经在许多系统上缩小了 CPU_COUNT
并取得了很好的效果。 运行 下面的查询查看最相关的并行参数。
select *
from v$parameter
where name in ('cpu_count', 'parallel_threads_per_cpu', 'parallel_degree_policy', 'parallel_degree_limit');
查找并行度 有多种方法可以查找 DOP 以及查找有关选择 DOP 的原因的信息。在19c中,explain plan的“Note”和“Hint Report”部分可以给出DOP是如何计算的详细信息。使用 explain plan for select ...
,然后使用 select * from table(dbms_xplan.display);
查找该信息。正如 astentx 所建议的,select dbms_sqltune.report_sql_monitor('&SQL_ID') from dual
对长 运行 查询也有很大帮助。
而不是为整个查询提供提示 - 您可以指定驱动 table。
/*+ 并行(A,8) */
然后制定解释计划,看看 DOP 是否到位。
SELECT /*+PARALLEL 8*/
A.ACC_ID,
COALESCE (B.PR_ID, NULL),
COALESCE (B.DESC, NULL),
COALESCE (B.CNT, 0)
FROM (SELECT ACC_ID
FROM ACC_ID_IN
WHERE XXX = 1 AND YYY = 'ABCD') A
LEFT OUTER JOIN
( SELECT /*+PARALLEL 8*/
A.ACC_ID,
B.PR_ID,
B.DESC,
COUNT (DISTINCT A.ACC_NBR) CNT
FROM DB1.TABLE1 A,
TABLE2 B,
TABLE3 C
WHERE A.ACC_ID IN (8888888888)
AND A.P_ID = B.P_ID
AND A.P_ID = C.P_ID
AND A.START <=TO_DATE (SUBSTR (A.ACC_ID, 1, 4) || '1231','YYYY/MM/DD')
AND A.END > TO_DATE (SUBSTR (A.ACC_ID, 1, 4) || '1230','YYYY/MM/DD')
GROUP BY A.ACC_ID, B.PR_ID, B.DESC
ORDER BY A.ACC_ID, B.PR_ID, B.DESC) B
ON A.ACC_ID = B.ACC_ID
WHERE A.ACC_ID IN (8888888888)
GROUP BY A.ACC_ID,
COALESCE (B.PR_ID, NULL),
COALESCE (B.DESC, NULL),
COALESCE (B.CNT, 0)
上面的带有并行提示的查询需要很长时间才能执行,而当我删除并行提示时相同的查询在几秒钟内执行。当 oracle 升级到 19c 时出现此问题。您能否帮助我了解这里发生了什么,我是否需要执行任何设置以启用并行提示作为数据库升级的一部分 activity。
并行性很棘手,并行度可能出乎意料的原因有很多。以下是您的查询的潜在问题,其中一些在评论中提到:
这么快的查询你还想要并行吗?并行更努力,而不是更聪明,所以你通常只想在大对象上使用它需要很长时间来处理。如果查询在没有并行性的情况下在几秒钟内运行,那么它可能首先不是并行性的好候选者。
语句级提示 查询顶部的
/*+ PARALLEL */
提示适用于整个语句,因此您不需要也向其他查询块添加提示。提示格式不正确 如果要指定并行度,需要在数字两边使用括号,如
/*+ PARALLEL(8) */
。如果没有括号,Oracle 将计算并行度。我什至不记得所有的规则和细节,但如果你要求 Oracle 为你生成 DOP,它通常会使用CPU_COUNT * PARALLEL_THREADS_PER_CPU * NUMBER_OF_INSTANCES
.CPU_COUNT 由于您刚刚升级,请检查
CPU_COUNT
是否已更改。在某些平台上,例如 Solaris,Oracle 将每个虚拟处理器计算为 CPU,然后仍将其乘以PARALLEL_THREADS_PER_CPU
,这可能会导致荒谬的数字。虽然那个参数看起来像是你不会碰的东西,但我已经在许多系统上缩小了CPU_COUNT
并取得了很好的效果。 运行 下面的查询查看最相关的并行参数。select * from v$parameter where name in ('cpu_count', 'parallel_threads_per_cpu', 'parallel_degree_policy', 'parallel_degree_limit');
查找并行度 有多种方法可以查找 DOP 以及查找有关选择 DOP 的原因的信息。在19c中,explain plan的“Note”和“Hint Report”部分可以给出DOP是如何计算的详细信息。使用
explain plan for select ...
,然后使用select * from table(dbms_xplan.display);
查找该信息。正如 astentx 所建议的,select dbms_sqltune.report_sql_monitor('&SQL_ID') from dual
对长 运行 查询也有很大帮助。
而不是为整个查询提供提示 - 您可以指定驱动 table。
/*+ 并行(A,8) */
然后制定解释计划,看看 DOP 是否到位。