【问题标题】:fastest way to insert 20 milion rows in Oracle在 Oracle 中插入 2000 万行的最快方法
【发布时间】:2015-03-24 08:41:50
【问题描述】:

我正在尝试从一个 oracle 数据库迁移到另一个。 我的 Select Query 非常复杂,它返回大约 2000 万条记录。 当我尝试执行时:

insert into xxx
select a, b, c, bla blaa
from yyy join zzz join ttt etc

大约需要 20 小时。

有什么不同的迁移方式吗? 你能给我什么建议吗?

感谢您的建议。

编辑: 我创建一个新表,如

create table XYZ as select a, b, c, bla blaa from yyy join zzz join ttt etc

大约需要 2 分钟。

现在我正在尝试从 XYZ 插入到我的原始表中。

还剩 15 分钟,继续:)

我会通知你的:)

【问题讨论】:

  • 导出为转储(使用EXPDP)并将其导入新数据库。这是最快的方式。
  • @Grcn,以防万一,您确定这是两个数据库,而不是同一个数据库中的两个模式。如果是,那么按照建议,使用EXPDP 导出表,并使用IMPDP 导入目标数据库架构中的表。
  • 基于您的本地表创建速度很快,为了进一步的诊断目的,您现在可以尝试在目标数据库中插入一个没有任何约束或索引的新的、完全空的表,看看需要多长时间。如果这也很快,请尝试从新的目标数据库表插入到您的实际目标表中,看看它是如何执行的。如果它很快,那么你有一点神秘 - 如果它很慢,那么问题根本不在于在远程表中运行单个插入,而可能是目标表上的索引、约束、触发器、物化视图等.
  • 在您插入目标表时,其他进程是否正在使用目标表,他们需要修改它还是只是读取它?
  • 我很高兴我建议的解决方案对您有用,如果您通过评论对我的回答给出状态,那就太好了。谢谢。

标签: sql oracle insert migration


【解决方案1】:

使用 SQL 查询在数据库之间移动大量数据可能是最糟糕的方式。

如果您必须那样做,至少要事先关闭目标表中的所有约束,在此过程中它们会占用相当多的 CPU。

更好的方法:Oracle 提供用于导入/导出和卸载/加载的实用程序,例如可以找到here

【讨论】:

  • 2000 万行...我不会真的认为这是一个非常大的数据量,但我们真的不知道,除非我们也有平均行宽。我还认为,如果您不知道是否有任何约束,或者在插入后重新启用它们的工作级别是什么(可能会增加约束的复杂性),那么建议禁用目标表上的约束还为时过早需要解决的违规行为)。这可能是所需工作量的净增加。
  • @David,“我正在尝试从一个 oracle 数据库迁移到另一个”这句话在我看来表明将数据移动到一个全新的(相同的)数据库,其中可以稍后添加约束(所有数据都不会违反约束,因为它来自具有约束的数据库)。这就是建议这样做的原因,尽管我对此仍有保留意见 - Oracle 提供了更好的方法。
  • 如果这是直接迁移到相同的数据库,那么我更倾向于同意,但我不希望在简单的迁移中涉及复杂的查询——更多的是直接选择。如果它是数据库的直接副本,那么我首先会考虑使用 RMAN 或可传输表空间(许可允许)。插入速度缓慢的原因可能是索引维护、约束检查、触发器执行、物化视图刷新……各种各样的事情。当然,知道这是一次性工作还是常规工作会很方便。
【解决方案2】:

操作的哪个部分花费的时间最多?是运行原始查询所涉及的工作(返回所有行的时间,而不仅仅是第一行),还是在数据库之间传输数据的时间(它们是在同一台机器上,还是在同一个数据中心的不同机器上,或在世界的另一端),或将数据插入表中(写入数据本身和UNDO/REDO?),或在目标表上维护索引和/或约束(如果有)?

一般来说,一个简单的 insert into ... select from ... 查询将是移动数据的最快方式,除非两者之间的网络连接很慢。由于 SQL*Net 传输中缺乏内在的并行性,非常大的数据集可能会出现问题,但通常不计算 2000 万行。

不过,作为一种您可以在那里执行的优化的尝试,SQL*Net 具有压缩在数据包内发送的数据的功能,因此如果网络时间很长并且可以激发更好的通过在 SELECT 阶段对数据进行排序进行压缩并且 ORDER 不会显着增加 SELECT 查询时间,然后您可以提高整体性能。不过,您必须考虑所有这些因素。

SELECT 查询可能会快速返回最初的几行数据,但它可能没有针对快速返回所有行进行很好的优化。默认情况下,调用 SELECT 作为 INSERT 的一部分应该会有所帮助,但只有通过运行包含 INSERT 子句的解释计划,您才有机会了解实际的查询优化计划。

使用直接路径插入(APPEND 优化器提示)可能会提高数据插入的速度,但这需要排他锁,并且还有一些其他记录在案的限制。

导出/导入方法需要在源数据库上运行相同的查询,然后是磁盘写入和磁盘空间来写入文件,然后是磁盘读取和网络时间以及磁盘写入来迁移它们,然后是磁盘空间来存储它们在目标机器上,然后磁盘读取以读取文件,然后在目标上几乎与插入语句相同的数据插入选项,所以除非你要使用表空间传输,否则我会考虑这是否真的改进。

长话短说——实际上是什么减缓了进程您是否看到源数据库、目标数据库或网络上的负载很高?

【讨论】:

    【解决方案3】:

    你可以试试这个,首先用你的查询创建一个表,然后从新创建的表中插入行,例如。

    create table XYZ as 
    select a, b, c, bla blaa
    from yyy join zzz join ttt etc
    
    insert into xxx
    select a, b, c, bla blaa
    from XYZ
    

    【讨论】:

    • 您能解释一下为什么这可能会提高流程的整体性能吗?
    • 我已经用这种方法处理了大约 400 万条记录,而且速度非常快。
    • 为什么它比简单的插入更快?
    猜你喜欢
    • 1970-01-01
    • 2020-08-10
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    相关资源
    最近更新 更多