在 Oracle 中通过脚本更快地插入的方法?

2024-01-02

我正在使用 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 表关联的序列或触发器,并且尚未为该表创建索引。


Problem

对于某些类型的语句,解析时间可能会呈指数增长,尤其是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 运行跟踪文件,您可以看到大量行的解析时间急剧增加。例如:

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. Try the insert into ... select ... from dual union all ...方法代替。它通常运行得更快,尽管它的解析性能也可能随着大小而显着降低。
  3. 升级甲骨文。新版本中的解析性能有所提高。在 12.2 版本中我无法再重现此问题。

Warning

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Oracle 中通过脚本更快地插入的方法? 的相关文章

  • 在 MySQL 中对整数字段运行带引号的数字(字符串)查询时会发生哪些复杂情况

    在 SQL 中 不应引用整数 因为如果引用 它将是一个字符串 但我很好奇如果我这样做会出现什么问题 并发症 例如 SELECT FROM table WHERE id 1 正确的 vs SELECT FROM table WHERE id
  • MySql 5.7 ORDER BY 子句不在 GROUP BY 子句中并且包含非聚合列

    我试图在不禁用 my ini 中的 only full group by 的情况下弄清楚 这是我的查询 SELECT p title COUNT t qty AS total FROM payments t LEFT JOIN produc
  • 如何在 DB2 AS/400 中将小数字段转换为日期字段?

    我有一个 DECIMAL 字段 其中包含 AS400 格式的日期 1100614 我努力了 cast MYDATE as DATE 但我无法将 DECIMAL 转换为 DATE 而 DATE MYDATE 返回空值 如何将此字段转换为日期字
  • 需要按天分割日期时间范围

    我有一个需要根据日期时间拆分的表 输入表 ID Start End A 2019 03 04 23 18 04 2019 03 04 23 21 25 A 2019 03 04 23 45 05 2019 03 05 00 15 14 所需
  • SQL 查询用于计算每个客户的订单数量和总金额

    我有两张桌子Order与列 OrderID OrderDate CID EmployeeID And OrderItem与列 OrderID ItemID Quantity SalePrice 我需要返回客户 ID CID 每个客户的订单数
  • 可以使用表通配符创建 sql 查询吗?

    这可能是一个简单的问题 但我无法在网上找到解决方案 任何帮助将不胜感激 我正在尝试在 PHP 中创建一个 SQL 查询 并希望以某种方式将通配符应用于 TABLE 过滤器 可能是这样的 select from table 但是 到目前为止我
  • Oracle:如何获取刚刚插入的行的序列号?

    如何获取刚刚插入的行的序列号 插入 返回 declare s2 number begin insert into seqtest2 x values aaa returning seq into s2 dbms output put lin
  • SQL 2008全文索引填充延迟

    我的经理说 在基础表数据更改后 可能需要一段时间才能更新全文搜索索引 例如 如果我有一张桌子Products有一个柱子Description我更新了该描述 然后我可能需要一些时间才能搜索该新描述 真的吗 这需要多长时间 SQL 2008 对
  • Reporting Services 在哪里存储其日志文件

    最相关的谷歌结果似乎表明 为了访问日志 我们必须将您自己的日志表部署到数据库并制作报告服务写入它 http technet microsoft com en us library ms157403 aspx 简而言之 Reporting S
  • 如何搜索例程的内容/(SP-触发函数)

    我需要在数据库内所有例程的例程主体 存储过程 函数 触发器 中搜索文本 我该怎么做 Thanks SELECT OBJECT NAME object id FROM sys sql modules WHERE definition LIKE
  • 如何通过子 POJO 的属性过滤复合 ManyToMany POJO?

    我有两个像这样的房间实体 Entity public class Teacher implements Serializable PrimaryKey autoGenerate true public int id ColumnInfo n
  • 在存储过程中验证用户的最简单方法?

    我需要一个存储过程 可以通过发送以下内容来检查登录尝试时他们是否是有效用户login and password查看它们在数据库中是否匹配 有没有一种简单的方法可以做到这一点 如果没有更多信息 我目前能提供的最好信息是 CREATE STOR
  • 快速查询最新记录的方法?

    我有一张这样的表 USER PLAN START DATE END DATE 1 A 20110101 NULL 1 B 20100101 20101231 2 A 20100101 20100505 在某种程度上 如果END DATE i
  • 提高第一个查询的性能

    如果执行以下数据库 postgres 查询 则第二次调用要快得多 我猜第一个查询很慢 因为操作系统 linux 需要从磁盘获取数据 第二个查询受益于文件系统级别和 postgres 中的缓存 有没有一种方法可以优化数据库以快速获得结果fir
  • 如何获取 Oracle 上 SYSDATE 的 UTC 值

    可能是一个经典 您知道在 Oracle 上检索 SYSDATE 的 UTC 值的简单技巧吗 最好也能在第 8 版上工作 现在我有自定义函数 Cheers Stefan 您可以使用 SELECT SYS EXTRACT UTC TIMESTA
  • 数字表与递归 CTE 生成一系列数字

    为什么使用数字表比使用递归 CTE 动态生成它们要快得多 在我的机器上 给定一张桌子numbers单列n 主键 包含从1到100000的数字 查询如下 select n from numbers 大约需要 400 毫秒才能完成 使用递归 C
  • 我不断收到错误“关系 [TABLE] 不存在”

    我一直在尝试查询数据库中的两个表 在服务器资源管理器中 我可以看到两个表 甚至可以看到其中的列 我们将它们称为 Schema table1 和 Schema table2 其中 Schema 的第一个字母大写 我尝试运行以下查询 selec
  • 快速将列的副本添加到 MySQL 表

    我需要一种快速的方法来复制表中的 DATETIME 列并为其指定一个新名称 我的表中有一个名为 myDate 的列 名为 myResults 我需要一个查询来在名为 newDate 的表中创建一个新列 该列的数据与 myDate 列完全相同
  • 在 DataView 的 RowFilter 中选择 DISTINCT

    我试图根据与另一个表的关系缩小 DataView 中的行范围 我使用的 RowFilter 如下 dv new DataView myDS myTable id IN SELECT DISTINCT parentID FROM myOthe
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData

随机推荐