暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 选择更新语句太慢

ASKTOM 2020-10-19
778

问题描述

嗨,康纳,克里斯,
我有一个FOR UPDATE SQL用于锁定ORDERS表中的某些行,但它似乎有点慢 (大约需要1分钟)。

我试着从dbms_xplan.display_awr获取计划。您能否从您过去的经验中给我一些线索,我可以寻找任何SQL调优的东西。

       SELECT PT.ORDER_ID
         FROM STAGING_001 PN
              JOIN GTT_TAB IDS ON IDS.MSG_ID = PN.MSG_ID,
              XMLTABLE (
                 'hsbcEnvelope/hsbcMessageBody/pymtTran'
                 PASSING PN.XML_MSG
                 COLUMNS REF_001 VARCHAR2 (50 CHAR) PATH 'REF_001',
                         REF_002 VARCHAR2 (50) PATH 'REF_001',
                         REF_003 VARCHAR2 (10 CHAR) PATH 'REF_001') PMT,
              ORDERS PT
        WHERE     1 = 1
              AND (   (    PMT.REF_002 IS NOT NULL
                       AND PMT.REF_001 IS NOT NULL
                       AND PMT.REF_002 = PT.REF_002
                       AND PT.REF_001 = PMT.REF_001
                       AND NVL (PMT.REF_003, :B1) = PT.REF_003)
                   OR (    PMT.REF_002 IS NOT NULL
                       AND PMT.REF_002 = PT.REF_002
                       AND NVL (PMT.REF_003, :B1) = PT.REF_003)
                   OR (    PMT.REF_001 IS NOT NULL
                       AND PT.REF_001 = PMT.REF_001
                       AND NVL (PMT.REF_003, :B1) = PT.REF_003)
      )
   FOR UPDATE OF PT.ORDER_ID NOWAIT;



-----------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                      | Name                   | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                               |                        |       |       | 27043 (100)|          |       |       |
|   1 |  FOR UPDATE                                    |                        |       |       |            |          |       |       |
|   2 |   BUFFER SORT                                  |                        |       |       |            |          |       |       |
|   3 |    CONCATENATION                               |                        |       |       |            |          |       |       |
|   4 |     NESTED LOOPS                               |                        |  1003 |  1935K| 11972   (1)| 00:00:01 |       |       |
|   5 |      NESTED LOOPS                              |                        |  2940 |  3930K|   210   (1)| 00:00:01 |       |       |
|   6 |       NESTED LOOPS                             |                        |    10 | 13630 |    13   (0)| 00:00:01 |       |       |
|   7 |        INDEX FAST FULL SCAN                    | SYS_C006227            |    10 |   130 |     2   (0)| 00:00:01 |       |       |
|   8 |        TABLE ACCESS BY INDEX ROWID             | STAGING_001            |     1 |  1350 |     2   (0)| 00:00:01 |       |       |
|   9 |         INDEX UNIQUE SCAN                      | PK_STG_INT             |     1 |       |     1   (0)| 00:00:01 |       |       |
|  10 |       XPATH EVALUATION                         |                        |       |       |            |          |       |       |
|  11 |      TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| ORDERS                 |     1 |   607 |     4   (0)| 00:00:01 | ROWID | ROWID |
|  12 |       INDEX RANGE SCAN                         | IDX_PT_REF_001         |     1 |       |     3   (0)| 00:00:01 |       |       |
|  13 |     NESTED LOOPS                               |                        |  1011 |  1950K| 14172   (1)| 00:00:01 |       |       |
|  14 |      NESTED LOOPS                              |                        |  3480 |  4652K|   249   (1)| 00:00:01 |       |       |
|  15 |       NESTED LOOPS                             |                        |    10 | 13630 |    13   (0)| 00:00:01 |       |       |
|  16 |        INDEX FAST FULL SCAN                    | SYS_C006227            |    10 |   130 |     2   (0)| 00:00:01 |       |       |
|  17 |        TABLE ACCESS BY INDEX ROWID             | STAGING_001            |     1 |  1350 |     2   (0)| 00:00:01 |       |       |
|  18 |         INDEX UNIQUE SCAN                      | PK_STG_INT             |     1 |       |     1   (0)| 00:00:01 |       |       |
|  19 |       XPATH EVALUATION                         |                        |       |       |            |          |       |       |
|  20 |      TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| ORDERS                 |     1 |   607 |     4   (0)| 00:00:01 | ROWID | ROWID |
|  21 |       INDEX RANGE SCAN                         | IDX_PT_REF_002         |     1 |       |     3   (0)| 00:00:01 |       |       |
|  22 |     NESTED LOOPS                               |                        |     1 |  1976 |   899   (1)| 00:00:01 |       |       |
|  23 |      NESTED LOOPS                              |                        |   204 |   272K|   287   (1)| 00:00:01 |       |       |
|  24 |       NESTED LOOPS                             |                        |    10 | 13630 |    13   (0)| 00:00:01 |       |       |
|  25 |        INDEX FAST FULL SCAN                    | SYS_C006227            |    10 |   130 |     2   (0)| 00:00:01 |       |       |
|  26 |        TABLE ACCESS BY INDEX ROWID             | STAGING_001            |     1 |  1350 |     2   (0)| 00:00:01 |       |       |
|  27 |         INDEX UNIQUE SCAN                      | PK_STG_INT             |     1 |       |     1   (0)| 00:00:01 |       |       |
|  28 |       XPATH EVALUATION                         |                        |       |       |            |          |       |       |
|  29 |      TABLE ACCESS BY GLOBAL INDEX ROWID        | ORDERS                 |     1 |   607 |     3   (0)| 00:00:01 | ROWID | ROWID |
|  30 |       INDEX UNIQUE SCAN                        | ORDERS_UK1             |     1 |       |     2   (0)| 00:00:01 |       |       |
-----------------------------------------------------------------------------------------------------------------------------------------
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

专家解答

首先,为了真正帮助您,我们需要查看语句正在做的工作-它处理了多少行,与估计值的比较,一致完成等。

要查看此信息,您需要:

-在运行查询之前,使用gather_plan_statistics提示运行查询或在会话中设置statistics_level = all
-获取格式为ALLSTATS LAST的计划

完成此操作后,请发布更新的执行计划以供我们检查。

也就是说,我怀疑where子句是否在执行作者的意图。

记住:

NULL = <任何事情> => 未知
NULL和 <任何东西> => 未知

查询永远不会返回这些行!

这意味着IS NOT NULL检查是不相关的。如果列具有null值,则它们的比较无论如何都将返回null。

虽然这并不重要,但删除不必要的子句会使查询更容易阅读。

这个谓词的情况更有趣:

nvl ( pmt.ref_003, :b1 ) = pt.ref_003


当它为null时,它将pmt.ref_003映射到bind变量,因此表达式减少到:

:b1 = pmt.ref_003 => :b1 = null => UNKNOWN


因此,所有这实际上是返回pmt.ref_003不为null的行。我怀疑它应该首先在nvl中绑定:

NVL (:B1, PMT.REF_003) = PT.REF_003


其次,如果条件:

pmt.ref_002 = pt.ref_002 and pt.ref_001  = pmt.ref_001


为真,那么后两个ORs子句也是真。所以要么:

-您可以删除第一个子句检查 (pmt.ref_002 = pt.ref_002和pt.ref_001 = pmt.ref_001)
-您可以删除后两个或子句
-条件需要重写,因此它们是互斥的 (例如pmt.ref_002 = pt.ref_002和pt.ref_001 <> pmt.ref_001等)

您需要执行的确切操作取决于此过程的业务逻辑。
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论