【问题标题】:Oracle Update statement hangingOracle Update 语句挂起
【发布时间】:2017-11-29 15:23:18
【问题描述】:

当同一脚本中以前的类似更新在大约一个小时内完成时,我有一条 Oracle Update 语句挂起。

我有两张桌子:

表 A:ID、Masked_Account、Original_Account(9+ 百万行,一个交叉引用表)。

表 B:UID、Prefix_Pan、Pan、Masked(1.3+ 十亿行)。

我正在尝试在 Table B Pan 列与 Table A Original_Account 列匹配的每个实例中使用 Table A Masked_Account 列更新 Table B Pan 列。

我正在分批更新每批 1 亿条记录,并随后提交。

例如,下面列出的更新 SQL 脚本在大约一个小时内完成:

UPDATE [TABLE B] optim
SET optim.PAN = (SELECT MASKED_ACCOUNT FROM [TABLE A] pans
                 WHERE optim.PAN = pans.ORIG_ACCOUNT), optim.MASKED = '1'
WHERE optim.OPTIM_UID BETWEEN 1200000000 AND 1300000000
AND EXISTS (SELECT 1
            FROM [TABLE A] pans
            WHERE optim.PAN = pans.ORIG_ACCOUNT);

我的最后一个更新 SQL 语句挂起并且永远不会完成:

UPDATE [TABLE B] optim
SET optim.PAN = (SELECT MASKED_ACCOUNT FROM [TABLE A] pans
                 WHERE optim.PAN = pans.ORIG_ACCOUNT), optim.MASKED = '1'
WHERE optim.OPTIM_UID > 1300000000
AND EXISTS (SELECT 1
            FROM [TABLE A] pans
            WHERE optim.PAN = pans.ORIG_ACCOUNT);

解释计划 (dbms_xplan.display) 结果:

Plan hash value: 4037184420

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name                         | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT                      |                              |   250 |  9250 |   465K  (1)| 00:00:10 |
|   1 |  UPDATE                               | OPTIM_SMRY_FTR_CHKMC_EXTRACT |       |       |            |          |
|*  2 |   HASH JOIN RIGHT SEMI                |                              |   250 |  9250 |   239K  (1)| 00:00:05 |
|   3 |    INDEX STORAGE FAST FULL SCAN       | IDX_PANS_ORIG_ACCT           |    82 |   902 | 10123   (1)| 00:00:01 |
|   4 |    TABLE ACCESS BY INDEX ROWID BATCHED| OPTIM_SMRY_FTR_CHKMC_EXTRACT |    32M|   796M|   228K  (1)| 00:00:05 |
|*  5 |     INDEX RANGE SCAN                  | PK_OP_47                     |    22M|       | 53465   (1)| 00:00:02 |
|   6 |   TABLE ACCESS BY INDEX ROWID BATCHED | PANS                         |     1 |    22 |   604   (1)| 00:00:01 |
|*  7 |    INDEX RANGE SCAN                   | IDX_PANS_ORIG_ACCT           |     1 |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OPTIM"."PAN"="PANS"."ORIG_ACCOUNT")
   5 - access("OPTIM"."OPTIM_UID">1300000000)
   7 - access("PANS"."ORIG_ACCOUNT"=:B1)

Note
-----
   - dynamic statistics used: dynamic sampling (level=AUTO)

谁能告诉我在最后一个更新 SQL (optim.OPTIM_UID > 1300000000) 上我需要做些什么不同的事情,这样它就不会挂起,或者我应该如何以不同的方式处理整个更新过程?

【问题讨论】:

  • 很多问题。在 1200000000 和 1300000000 之间真的有 100 毫米的行吗?我的猜测是没有。您可能有更多行大于 1300000000。您检查过阻塞锁吗?它似乎在移动吗? (使用撤消/回滚)您的 dbas 怎么说?
  • 在 1200000000 和 1300000000 之间确实有 1 亿行。Optim_UID 确实是“rownum”。表 B 的总行数为 1,322,566,115。上次我尝试运行最后一批更新(> 1300000000)时,我没有看到任何阻塞锁,但已经运行了 22 多个小时。由于其他更高的优先级,目前无法让数据库管理员查看它。
  • 13 亿次更新,每一次更新都需要对 masked_account 的子查询。而且我相信 EXISTS 部分也会为每一行触发。加入两个表并插入工作表可能会更快吗?然后删除并重命名? optim.PAN 上是否有可以先禁用的索引?
  • 能否请您在更新中运行解释计划并使用结果编辑问题。
  • 如果在慢查询或挂起查询运行时查看 V$SESSION 中的 EVENT,您可以查看它是否正在等待锁定。锁是一种排队等待事件。您还可以在各种 GUI 工具中看到这一点。

标签: oracle


【解决方案1】:

依靠OPTIM.MASKED 列代替在谓词中使用相关子查询

听起来optim.masked 列仅在被屏蔽后才设置为1。最好知道它的默认行为。

-可以设置成NULL吗?

-也许默认设置为0

-该列有什么限制?

假设它可以设置为NULL,并且在它被屏蔽后才设置为1,你能不能这样做(删除谓词中的相关子查询):

 UPDATE [TABLE b] optim
SET optim.pan = (SELECT masked_account FROM [TABLE A] pans
                 WHERE optim.pan = pans.orig_account), 
    optim.masked = '1'
WHERE optim.masked != '1'
OR optim.masked IS NULL;

这种方法假定谓词中的相关子查询是性能和锁定问题的根源。


您应该检查您的语句是否导致锁定是查询 v$locked_object 视图并查找与您的会话关联的锁定。


如果我们不能依赖 optim.masked 来更新 optim 表,我会考虑使用 Merge 语句来避免相关子查询。表 A 有一个给定 orig_account 的记录(这是合并的确定性功能所必需的)。您可以查看表 A 的主键是什么。我假设 orig_account 是主键。

MERGE INTO [TABLE b] optim USING [TABLE A] pans ON ( optim.pan = pans.orig_account )
WHEN MATCHED THEN UPDATE SET optim.pan = pans.masked_account,
optim.masked = '1';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 2014-10-30
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    相关资源
    最近更新 更多