【问题标题】:Oracle multi insert statementOracle 多插入语句
【发布时间】:2011-05-17 19:16:27
【问题描述】:

在我的应用程序中,我必须添加许多记录。我正在使用以下构造:

   INSERT /*+ append parallel(t1, 4) parallel(t2, 4) */ ALL
   INTO t1 (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3')
   INTO t2 (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3')
   INTO t2 (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3')
   .
   .
   .
SELECT 1 FROM DUAL;

我也在使用 APPEND 和 PARALLEL 提示。请注意,我在两个不同的表中插入数据。似乎并行被忽略了(DBA 告诉我)。那么我怎么知道它是否被使用呢?是否可以在这样的构造中使用 PARALLEL 提示?有效吗?

【问题讨论】:

  • 你的陈述中的提示在哪里?这实际上是您使用的语句吗?什么,你到底想并行做什么?作为多表插入的一部分,您是否有实际查询,或者使用 DUAL 只是对您正在做的事情的粗略简化?你在使用 PARALLEL DML 吗?
  • 我添加了提示。我正在尝试使用 Direct Path 并利用并行性通过单个命令添加许多记录。问题是插入没有利用并行性。我想知道为什么以及如何检查它是否被使用。
  • 多少是“许多记录”,几十个还是几百万个?
  • 每条语句大约 30 条记录。
  • 所有答案都非常有帮助。不幸的是,我不能全选。非常感谢。

标签: oracle query-hints


【解决方案1】:

这可能足以让它工作:

alter session enable parallel dml;

您可以使用这样的查询来检查实际的并行度:

select px_servers_executions, v$sql.*
from v$sql where lower(sql_text) like '%insert%parallel%' order by last_load_time desc;

如果您仍然没有获得并行性,有很多可能的原因。首先,看看这些参数:

select * from v$parameter where name like 'parallel%'

但您可能不希望您的插入语句具有并行性。并行性具有大量开销,并且通常仅在处理数千或数百万条记录时才有用。

我猜你真正的问题是解析大型 SQL 语句的时间。多表插入尤其糟糕。如果您尝试插入超过几百行,您的查询将需要几秒钟的时间来解析。根据您的 Oracle 版本,如果您尝试使用 501 表,它将永远挂起。运行几个较小的查询而不是一个大型查询要快得多。例如,100 行的 5 次插入将比 500 行的 1 次插入运行得快得多。 (一般来说,这与如何为 Oracle 进行性能调整完全相反。这是一种特殊情况,因为与解析大型 SQL 语句相关的错误。)

【讨论】:

    【解决方案2】:

    APPEND hint 仅支持 INSERT 语句的子查询语法,不支持 VALUES 子句。如果您使用 VALUES 子句指定 APPEND 提示,它将被忽略并使用常规插入。要将直接路径 INSERT 与 VALUES 子句一起使用,请参阅“APPEND_VALUES 提示”。

    【讨论】:

      【解决方案3】:

      在某些情况下并行性被禁用。包括,从 Oracle documentation:

      已为 DML 禁用并行性 对您拥有的表进行操作 定义了触发器或引用 完整性约束。

      这对我来说似乎是一个很大的限制。您的表上有触发器或外键吗?

      【讨论】:

        【解决方案4】:

        为 30 条记录启用并行性会浪费资源。并行性涉及昂贵的开销(拆分工作、分配进程、同步结果......),对于如此小的操作来说,这不值得。

        如果你想把它优化得那么糟糕,我想你正在执行这个语句数百万次。在这种情况下,找到一种方法将这百万条语句转换为大集合操作可能会更有效——这可以很好地从并行性中获益。


        更新:另一个想法可能是运行多个会话的语句,有效地实现 DIY 并行性。您能否设计您的流程,让多个会话同时读取输入数据并插入?

        【讨论】:

        • 嗨,维森特。这是不可能的。我的应用程序正在读取数百万条记录、处理它们并写入结果(合并)。我尝试了几种解决方案,例如用于在内存中收集记录并使用批量操作写入它们的包,但它降低了性能(为每条记录调用存储过程的开销)。
        • @Eduardo:你能分工让多个进程同时处理插入吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-21
        • 1970-01-01
        • 2015-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多