【问题标题】:Faster way to Insert, via script, in Oracle?在 Oracle 中通过脚本更快地插入?
【发布时间】:2012-07-24 06:09:00
【问题描述】:

我正在使用 C# .NET 4.0 应用程序,它使用 ODP.NET 11.2.0.2.0 和 Oracle 11g 数据库。该应用程序预加载了一些带有数据的查找表,并且由于大多数的记录少于 20 条,因此脚本运行得非常快。但是,其中一个脚本有 802 条记录,并且需要 248.671 秒来插入记录,对于这样的少量数据和一个宣传大量数据的快速操作的数据库来说,这似乎是多余的。

所以我想知道,有没有比当前编写脚本的方式更快的方式通过脚本插入数据?

要插入的表是这样定义的:

CREATE TABLE FileIds
(
     Id                 NUMERIC(38)                         NOT NULL
    ,Name               NVARCHAR2(50)   DEFAULT 'Unknown'   NOT NULL 
    ,FileTypeGroupId    NUMERIC(38)                         NOT NULL
    ,CONSTRAINT FK_FileIds_FileTypeGroups FOREIGN KEY ( FileTypeGroupId ) REFERENCES FileTypeGroups ( Id )
)

要插入的脚本如下所示:

BEGIN
    INSERT ALL
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1152,5)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1197,10)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1200,6)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1143,3)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1189,9)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1109,7)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1166,4)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (0,8)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1149,2)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1400,1)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1330,11)
        INTO FileIds ( Id, FileTypeGroupId ) VALUES (1000,0)
        -- 790 Records removed for example purposes.
        SELECT * FROM DUAL;
    COMMIT;
END;

外键中引用的 FileTypeGroups 表是在加载 FileIds 表之前预加载的。没有与 FileIds 表关联的序列或触发器,并且尚未为该表创建索引。

【问题讨论】:

  • 对我来说看起来不错。已经通过 Database Tuning Advisor 检查出了什么问题?
  • 没有。我对 Oracle 还是很陌生,对 Database Tuning Advisor 一无所知。是像 SQL Developer 这样的单独应用,还是需要加载到 SQL Developer 中的包?
  • 什么版本的Oracle?一些精简的版本没有所有的工具。必须有其他事情发生,因为即使在最慢的硬件上,802 记录也需要不到一秒钟的时间。确保没有其他可能持有锁的事务。
  • C# 可以做“批处理语句”吗?在 Java 中,使用 Oracle JDBC 驱动程序的速度非常快。
  • @JOTN 根据sqlplus,版本为:Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production,PL/SQL Release 11.2.0.3.0 - Production,CORE 11.2.0.3。 0 生产,64 位 Windows 的 TNS:版本 11.2.0.3.0 - 生产,NLSRTL 版本 11.2.0.3.0 - 生产

标签: sql oracle plsql


【解决方案1】:

问题

解析时间可能会随着某些类型的语句成倍增加,尤其是INSERT ALL。例如:

--Clear any cached statements, so we can consistently reproduce the problem.
alter system flush shared_pool;
alter session set sql_trace = true;

--100 rows
INSERT ALL
    INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
    ...
    repeat 100 times
    ...
select * from dual;

--500 rows
INSERT ALL
    INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
    ...
    repeat 500 times
    ...
select * from dual;

alter session set sql_trace = false;

通过 tkprof 运行跟踪文件,您可以看到大量行的 Parse 时间急剧增加。例如:

100 行:

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.06       0.05          0          1          0           0
Execute      1      0.00       0.00          0        100        303         100
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.06       0.05          0        101        303         100

500 行:

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1     14.72      14.55          0          0          0           0
Execute      1      0.01       0.02          0        502       1518         500
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2     14.74      14.58          0        502       1518         500

解决方案

  1. 将您的大型语句分成几个较小的语句。很难找到最佳尺寸。在某些版本的 Oracle 中,会导致问题的行数非常多。我通常会选择大约 100 行 - 足以获得分组语句的大部分好处,但又足够低以避免解析错误。或者...
  2. 改用insert into ... select ... from dual union all ... 方法。它通常运行得更快,尽管它的解析性能也可能随着大小而显着下降。
  3. 升级甲骨文。解析性能在较新版本中有所提高。我无法再在 12.2 版中重现此问题。

警告

不要从中吸取错误的教训。如果您担心 SQL 性能,那么在 99% 的情况下,您最好将相似的事物组合在一起,而不是将它们分开。你以正确的方式做事,你只是遇到了一个奇怪的错误。 (我搜索了 My Oracle Support,但找不到官方的错误。)

【讨论】:

  • 哇,切换到 UNION ALL 方法有很大的不同(0.497 秒)。谢谢! :) 另外,谢谢你的警告,这是一个很好的教训。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2011-02-06
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
相关资源
最近更新 更多