【问题标题】:Oracle insert performs too longOracle 插入执行时间过长
【发布时间】:2023-04-05 06:48:01
【问题描述】:

我对 Oracle 10g XE 执行插入的时间感到困惑。我通过编程事务管理实现了从 xml 文件批量插入到几个表中。为什么一个插入片刻执行,另一个插入超过 10 分钟!我等不及要停下来了。我认为还有更复杂的事情我还没有注意。

更新:

我使用 Monitor 找到了锁。

Waits     
Event   enq: TX - row lock contention
name|mode   1415053316
usnusnusnusn<<16 | slot 327711
sequence    162

SQL   
INSERT INTO ESKD$SERVICESET (ID, TOUR_ID, CURRENCY_ID) VALUES (9, 9, 1)

这是什么意思,我应该如何解决?

【问题讨论】:

  • 你的问题描述非常模糊。请更清楚什么是长的,什么是快的,以及在什么情况下(你在使用事务吗?批量插入?impdp?...)
  • 请显示一些您用于插入的代码。并描述你所谓的“程序化事务管理”。我们在谈论多少数据(插入的行数)?您使用什么语言来解析 XML?
  • 确实很模糊。性能不佳的许多可能原因:某些表上的复杂触发器、其他用户打开的事务、插入数据的表的当前大小、表上的当前索引。还有更多...
  • 有多少会话同时修改同一个表?由于是插入,因此冲突不能直接在插入的行上,而可能在唯一约束索引或被引用表的主键索引中。
  • 什么是“程序化事务管理”

标签: oracle insert locking


【解决方案1】:

TX- Enqueues 是众所周知的,快速的 google 会给你一个明确的answer

来自那篇文章:

1) 当一个会话正在等待另一个会话已经持有的行级锁时,会在模式 6 中等待 TX。当一个用户正在更新或删除另一会话希望更新或删除的行时,就会发生这种情况。这种类型的 TX enqueue wait 对应等待事件 enq: TX - row lock contention。

如果您同时对表进行大量插入和更新,您希望每个事务尽可能短。进来,出去……中间的时间越长,其他交易的延迟就越长。

纯属猜测:

我感觉您提到的“程序化事务管理”是您尝试使用像 QUEUE 这样的表。插入开始记录,经常更新它以更改状态,然后删除“完成”的记录。那总是麻烦。

【讨论】:

    【解决方案2】:

    这个问题真的很难用这么少的具体信息来回答。我只能告诉你为什么会这样。

    如果您正在执行INSERT ... SELECT ... 批量插入,那么您的SELECT 查询可能表现不佳。可能存在大量的表连接、内联视图的低效使用和其他可能对您的INSERT 的性能产生负面影响的资源。

    尝试在解释计划中执行您的SELECT 查询,以查看优化器如何导出计划并评估查询的成本。

    您提到的另一件事是可能的锁定。可能是这种情况,但您需要使用 OEM 工具进行分析才能确定。

    要考虑的另一件事可能是您的表上没有索引,或者这些表上的统计信息可能已过时。过时的统计信息会极大地影响对大型表的查询性能。

    【讨论】:

      【解决方案3】:

      请参阅 sites.google.com/site/embtdbo/wait-event-documentation/oracle-enqueues

      锁定等待表示可能很容易导致性能问题的冲突。从表面上看,问题很可能是插入了重复的键值,而该键值的第一次插入尚未提交。您看到“enq: TX - row lock contention”的锁发生是因为一个会话试图修改来自另一个会话的未提交数据。此特定锁定等待事件有 4 个常见原因:

      1. 更新/删除同一行
      2. 插入相同的唯一键
      3. 修改同一个位图索引块
      4. 将父值删除/更新为外键

      如果您正在执行插入,我们可以消除第一个和最后一个情况。 如果您没有涉及位图索引,您应该能够识别第二个。如果您涉及位图索引并且涉及 uniq 键,那么您可以轻松调查是否有活动会话历史 (ASH) 数据,但不幸的是 Oracle XE 没有。另一方面,您可以使用 S-ASH 自己收集它,请参阅:http://ashmasters.com/ash-simulation/。使用 ASH 或 S-ASH,您可以运行类似的查询

      a22 的 col 事件 a18 的 col 块类型 a18 的 col objn a10 的色标 col fn 为 99 col sid 为 9999 col bsid 为 9999 col lm for 99 col p3 为 99999 col blockn 为 99999 选择 to_char(sample_time,'HH:MI') st, substr(event,0,20) 事件, ash.session_id sid, mod(ash.p1,16)lm, ash.p2, ash.p3, nvl(o.object_name,ash.current_obj#) objn, substr(o.object_type,0,10) otype, CURRENT_FILE# fn, CURRENT_BLOCK# blockn, ash.SQL_ID, BLOCKING_SESSION bsid --,ash.xid 来自 v$active_session_history ash, all_objects o 像“enq:TX %”这样的事件 和 o.object_id (+)= ash.CURRENT_OBJ# 按 sample_time 排序 / 这将输出如下内容: ST EVENT SID LM P2 P3 OBJ OTYPE FN BLOCKN SQL_ID BSID 10:41 enq: TX - 行锁 c 143 4 966081 4598 I1 INDEX 0 0 azav296xxqcjx 144 10:41 enq: TX - 行锁 c 143 4 966081 4598 I1 INDEX 0 0 azav296xxqcjx 144 10:41 enq: TX - 行锁 c 143 4 966081 4598 I1 INDEX 0 0 azav296xxqcjx 144 10:41 enq: TX - 行锁 c 143 4 966081 4598 I1 INDEX 0 0 azav296xxqcjx 144 显示存在争用的对象名称“OBJ”和对象类型“OTYPE”,并且类型是 INDEX。从那里您可以查找 INDEX 的类型以验证它是位图。 如果问题是位图索引,那么您可能应该使用位图索引重新评估或重新访问数据加载和/或修改的方式以减少冲突。

      如果问题不是 BITMAP 索引,那么它正在尝试插入重复键。其他一些进程已插入相同的键值但尚未提交。然后您的进程尝试插入相同的键值,并且必须等待第一个会话提交或回滚。

      有关更多信息,请参阅此链接:锁定等待

      【讨论】:

        【解决方案4】:

        这意味着,您的序列缓存太小。增加它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-26
          • 2021-03-30
          • 1970-01-01
          • 2018-01-19
          • 2023-03-16
          • 1970-01-01
          • 1970-01-01
          • 2017-10-18
          相关资源
          最近更新 更多