【问题标题】:Does Parallel Hint within Dynamic SQL of Oracle run in parallel?Oracle 的动态 SQL 中的 Parallel Hint 是否并行运行?
【发布时间】:2021-09-22 15:51:12
【问题描述】:

我将 DML 和 DDL 作为我的程序的一部分,并在 DML 和 DDL 上启用了并行。我想使用并行提示在并行模式下运行它们,但它们都不是并行执行的。这是使用动态 SQL 的限制吗?

例如

DECLARE
v_parallel_degree NUMBER := 8;
BEGIN
    EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL DML PARALLEL ' || v_parallel_degree;
    EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL QUERY PARALLEL ' || v_parallel_degree;
    EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL DDL PARALLEL ' || v_parallel_degree;

    EXECUTE IMMEDIATE 'INSERT /*+PARALLEL(DEFAULT)*/ INTO '|| p_target_tabname || ' NOLOGGING
                SELECT /*+PARALLEL(dmf,DEFAULT)*/*
                FROM ' || p_source_tabname ||' PARTITION('|| p_part_name ||');
    
    EXECUTE IMMEDIATE 'CREATE UNIQUE INDEX idx_pk ON TAB_HIST
                 (COL1,COL2,COL3)
                 LOCAL
                 NOLOGGING PARALLEL ' || v_parallel_degree;
END;

我什至尝试了下面的块但没有工作。

v_sql := 'BEGIN
                EXECUTE IMMEDIATE ''ALTER SESSION FORCE PARALLEL DML PARALLEL ' || v_parallel_degree ||''';
                EXECUTE IMMEDIATE ''ALTER SESSION FORCE PARALLEL QUERY PARALLEL ' || v_parallel_degree ||''';
                INSERT /*+PARALLEL(DEFAULT)*/ INTO '|| p_target_tabname || ' NOLOGGING
                SELECT /*+PARALLEL(dmf,DEFAULT)*/*
                FROM ' || p_source_tabname ||' PARTITION('|| p_part_name ||') dmf;
    DBMS_OUTPUT.PUT_LINE(''Inserted '' || SQL%ROWCOUNT || '' Rows into Table- '' || p_target_tabname || '' Partition - '' || p_part_name );
                COMMIT;
              END;';
    EXECUTE IMMEDIATE v_sql;
Oracle Version -
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
CORE    12.1.0.2.0  Production

很快将升级到 19c。

任何建议都表示赞赏..

TIA 文卡特

【问题讨论】:

  • 您如何确定它们不是以并行模式运行的?
  • @astentx,我没有用任何查询验证这一点,但我发现执行时间与同一过程中的简单插入相比存在差异,在该过程中插入 14M 行只需 10 秒使用动态 SQL 2 分钟。还观察了我的会话浏览器中的会话数。我正在研究此处提供的其他答案。谢谢大家的回答,我们会尽快回复您。

标签: oracle dynamic-sql


【解决方案1】:

TLDR

很可能您忘记启用并行 DML。

ALTER SESSION ENABLE PARALLEL DML;

此外,如果您强制并行执行,您通常不要使用并行提示,反之亦然。

示例设置 (11.2)

create table TAB_HIST (
col1 int,
col2 int,
col3 varchar2(4000))
PARTITION BY RANGE (col1) 
interval(1000000)
(
  partition p_init values less than (1000000) 
); 


create table TAB_SRC (
col1 int,
col2 int,
col3 varchar2(4000)
)
PARTITION BY RANGE (col1) 
interval(1000000)
(
  partition p_init values less than (1000000) 
);

insert into tab_src
select rownum, rownum,  rpad('x',1000,'y') from dual connect by level <= 100000;
commit;

插入

第一步必须enable parallel DML

ALTER SESSION ENABLE PARALLEL DML;

请注意,也可以使用提示

INSERT /*+ ENABLE_PARALLEL_DML */ …

此外,如果您强制并行 DML 和 QUERY,则通常不使用 并行提示。我在暗示直接插入 APPEND,这在这种情况下经常使用。

DECLARE
v_parallel_degree NUMBER := 2;
BEGIN
    EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL DML PARALLEL ' || v_parallel_degree;
    EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL QUERY PARALLEL ' || v_parallel_degree;

    EXECUTE IMMEDIATE 'INSERT /*+ APPEND */ INTO TAB_HIST  
                SELECT  *
                FROM  TAB_SRC PARTITION(P_INIT)';
END;
/

如何检查表是否被并行插入? 最简单的方法是查询表(在提交之前)——如果你得到下面的错误,那就是并行直接插入。

select count(*) from TAB_HIST;
ORA-12838: cannot read/modify an object after modifying it in parallel

索引

如果您在create index 语句中指定并行度,则不需要enableforce 任何东西。

DECLARE
v_parallel_degree NUMBER := 2;
BEGIN
    
    EXECUTE IMMEDIATE 'CREATE UNIQUE INDEX idx_pk ON TAB_HIST
                 (COL1,COL2,COL3)
                 LOCAL
                 NOLOGGING PARALLEL ' || v_parallel_degree;
END;
/

检查就像查看数据字典中的度数一样简单

select DEGREE from user_indexes where table_name = 'TAB_HIST';

DEGREE 
--------- 
2

请注意,在并行模式下创建索引后,您通常希望将 DOP 重置为 1。否则一些简单的嵌套循环查询可能会被混淆,并会打开一个并行查询...

【讨论】:

  • 你是对的,我应该启用并行而不是强制并行。是的,在并行模式下创建索引后,我有另一个非并行的更改索引。非常感谢你帮助我。这让我的努力重回正轨。现在,对于 480M 行,Simple insert 和动态 SQL 都在
  • 很抱歉再次打扰您,现在即使 ENABLE PARALLEL DML 也不适合我,我可以监控会话是否按顺序执行。直到昨天,相同的代码都运行良好。您是否想到任何强制我的会话在单线程中运行的数据库参数?
  • 数十种可能的原因@Venkat。如果您看到 Servers Available,请检查 V$PX_PROCESS_SYSSTAT`。在v$PX_SESSTAT 中查找Parallel operations downgraded to serial 的出现情况
  • 当我签入 V$PX_PROCESS_SYSSTAT 并且每个查询的编号都在变化时,服务器可用。我没有安静地得到第二部分。我是目前唯一使用此数据库服务器的开发人员。我不明白拾取并行线程的不一致,当我使用 8 时,有时会在 8 上运行,有时在 6 或 4 或 1 上运行。在对此问题进行一些研究后,我什至将以下语句添加到我的代码中` ``立即执行'ALTER SESSION SET parallel_degree_policy =''AUTO''';立即执行'ALTER SESSION SET parallel_min_time_threshold = 2'; ```
【解决方案2】:
【解决方案3】:

你可以从它开始:https://stackoverflow.com/a/67377464/429100

然后你可以查看一个真正的执行计划(Note section)和RTSM(Real-time SQL Monitor)报告(select/*+ no_monitor */ dbms_sqltune.report_sql_monitor(sql_id =&gt; '&amp;1',report_level =&gt; 'ALL',type =&gt; 'TEXT') sqlmon from dual;)。它们应该显示有关使用的 DOP 的更多信息。

最后,您可以使用以下命令跟踪并行执行:

alter session set "_px_trace"="compilation","execution","messaging";

更多信息:“Tracing Parallel Execution with _px_trace (Doc ID 444164.1)

【讨论】:

  • 感谢您的宝贵时间,对我来说信息太多了。作为一名开发人员,我似乎无法访问跟踪。珍惜你的时间
猜你喜欢
  • 1970-01-01
  • 2017-05-21
  • 2019-12-02
  • 2012-10-19
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
  • 2013-08-16
相关资源
最近更新 更多