Oracle嵌套查询性能

时间:2017-05-15 14:10:26

标签: oracle

我正在尝试构建一个具有两个级别的复杂查询(一个父查询具有嵌套查询)。在一个非常低的水平我有这样的事情:

SELECT *
   from (SELECT a.1 a1,
                a.2 a2,
                a.3 a3,
                b.1 b1,
                b.2 b2,
                b.3 b3
           from a
           join b
             on a.1 = b.1) sq
  where sq.b3 = '123'

使用这种方法,查询会变成花费大量时间,而下面这样做是立即...

SELECT *
   from (SELECT a.1 a1,
                a.2 a2,
                a.3 a3,
                b.1 b1,
                b.2 b2,
                b.3 b3
           from a
           join b
             on a.1 = b.1
           where sq.b3 = '123') sq

我知道嵌套查询会影响性能,但我希望优化器能够“改善”#34;它并带来更高的效率...

问题是我需要在父查询中使用第一种方法,因为它具有很大的复杂性,所以我会在嵌套查询中放置大量的验证...

出了什么问题?

编辑:添加更多信息

下面我添加了一个简化版本的查询,我仍然看到了性能问题(将过滤器放在OUTSIDE嵌套查询或INSIDE中)。还添加了相应的执行计划:

在嵌入的查询中过滤(效果很好)

 select resultset.*
   from (select first_value(ord.stcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_stcust,
                first_value(ord.st_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_st_adr_id,
                first_value(ord.rtcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_rtcust,
                first_value(ord.rt_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_rt_adr_id,
                first_value(ord.btcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_btcust,
                first_value(ord.bt_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_bt_adr_id,
                first_value(ord.brcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_brcust,
                first_value(ord.br_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_br_adr_id,
                invdtl.dtlnum
           from shipment
          inner
           join shipment_line
             on (shipment.ship_id = shipment_line.ship_id)
          inner
           join invdtl
             on (shipment_line.ship_line_id = invdtl.ship_line_id)
          inner
           join invsub
             on (invdtl.subnum = invsub.subnum)
          inner
           join invlod
             on (invsub.lodnum = invlod.lodnum)
          inner
           join ord_line
             on (shipment_line.ordnum = ord_line.ordnum and shipment_line.ordlin = ord_line.ordlin and shipment_line.ordsln = ord_line.ordsln and shipment_line.wh_id = ord_line.wh_id and shipment_line.client_id = ord_line.client_id)
          inner
           join ord
             on (ord_line.ordnum = ord.ordnum and ord_line.wh_id = ord.wh_id and ord_line.client_id = ord.client_id)
           left
           join ctnmst invlod_ctnmst
             on (invlod.vc_ctncod = invlod_ctnmst.ctncod and invlod.wh_id = invlod_ctnmst.wh_id)
           left
           join ctnmst invsub_ctnmst
             on (invsub.vc_ctncod = invsub_ctnmst.ctncod and invlod.wh_id = invsub_ctnmst.wh_id)
           left
           join prtftp_dtl
             on (invdtl.prtnum = prtftp_dtl.prtnum and invdtl.ftpcod = prtftp_dtl.ftpcod and invlod.wh_id = prtftp_dtl.wh_id and invdtl.prt_client_id = prtftp_dtl.prt_client_id and 0 = prtftp_dtl.uomlvl)
          where invdtl.dtlnum = 'D00000525035') resultset

在嵌套查询中执行计划过滤

Plan hash value: 337977667

------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                  |     1 |   398 |    11  (10)| 00:00:01 |
|   1 |  VIEW                                   |                  |     1 |   398 |    11  (10)| 00:00:01 |
|   2 |   WINDOW SORT                           |                  |     1 |   869 |    11  (10)| 00:00:01 |
|   3 |    NESTED LOOPS OUTER                   |                  |     1 |   869 |    10   (0)| 00:00:01 |
|   4 |     NESTED LOOPS OUTER                  |                  |     1 |   842 |     9   (0)| 00:00:01 |
|   5 |      VIEW                               |                  |     1 |   834 |     8   (0)| 00:00:01 |
|   6 |       NESTED LOOPS                      |                  |     1 |   284 |     8   (0)| 00:00:01 |
|   7 |        NESTED LOOPS                     |                  |     1 |   196 |     7   (0)| 00:00:01 |
|   8 |         NESTED LOOPS OUTER              |                  |     1 |   171 |     6   (0)| 00:00:01 |
|   9 |          NESTED LOOPS                   |                  |     1 |   163 |     5   (0)| 00:00:01 |
|  10 |           NESTED LOOPS                  |                  |     1 |   143 |     4   (0)| 00:00:01 |
|  11 |            NESTED LOOPS                 |                  |     1 |   132 |     3   (0)| 00:00:01 |
|  12 |             NESTED LOOPS                |                  |     1 |    85 |     2   (0)| 00:00:01 |
|  13 |              TABLE ACCESS BY INDEX ROWID| INVDTL           |     1 |    56 |     1   (0)| 00:00:01 |
|* 14 |               INDEX UNIQUE SCAN         | INVDTL_PK        |     1 |       |     1   (0)| 00:00:01 |
|  15 |              TABLE ACCESS BY INDEX ROWID| INVSUB           |     1 |    29 |     1   (0)| 00:00:01 |
|* 16 |               INDEX UNIQUE SCAN         | INVSUB_PK        |     1 |       |     1   (0)| 00:00:01 |
|  17 |             TABLE ACCESS BY INDEX ROWID | SHIPMENT_LINE    |     1 |    47 |     1   (0)| 00:00:01 |
|* 18 |              INDEX UNIQUE SCAN          | SHIPMENT_LINE_PK |     1 |       |     1   (0)| 00:00:01 |
|* 19 |            INDEX UNIQUE SCAN            | SHIPMENT_PK      |     1 |    11 |     1   (0)| 00:00:01 |
|  20 |           TABLE ACCESS BY INDEX ROWID   | INVLOD           |     1 |    20 |     1   (0)| 00:00:01 |
|* 21 |            INDEX UNIQUE SCAN            | INVLOD_PK        |     1 |       |     1   (0)| 00:00:01 |
|* 22 |          INDEX UNIQUE SCAN              | CTNMST_PK        |     1 |     8 |     1   (0)| 00:00:01 |
|* 23 |         INDEX UNIQUE SCAN               | ORD_LINE_PK      |     1 |    25 |     1   (0)| 00:00:01 |
|  24 |        TABLE ACCESS BY INDEX ROWID      | ORD              |     1 |    88 |     1   (0)| 00:00:01 |
|* 25 |         INDEX UNIQUE SCAN               | ORD_PK           |     1 |       |     1   (0)| 00:00:01 |
|* 26 |      INDEX UNIQUE SCAN                  | CTNMST_PK        |     1 |     8 |     1   (0)| 00:00:01 |
|* 27 |     TABLE ACCESS BY INDEX ROWID         | PRTFTP_DTL       |     1 |    27 |     1   (0)| 00:00:01 |
|* 28 |      INDEX RANGE SCAN                   | PRTFTP_DTL_IDX1  |     3 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------

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

  14 - access("INVDTL"."DTLNUM"='D00000525035')
  16 - access("INVDTL"."SUBNUM"="INVSUB"."SUBNUM")
  18 - access("SHIPMENT_LINE"."SHIP_LINE_ID"="INVDTL"."SHIP_LINE_ID")
  19 - access("SHIPMENT"."SHIP_ID"="SHIPMENT_LINE"."SHIP_ID")
  21 - access("INVSUB"."LODNUM"="INVLOD"."LODNUM")
  22 - access("INVLOD"."VC_CTNCOD"="INVLOD_CTNMST"."CTNCOD"(+) AND 
              "INVLOD"."WH_ID"="INVLOD_CTNMST"."WH_ID"(+))
  23 - access("SHIPMENT_LINE"."ORDNUM"="ORD_LINE"."ORDNUM" AND 
              "SHIPMENT_LINE"."ORDLIN"="ORD_LINE"."ORDLIN" AND "SHIPMENT_LINE"."ORDSLN"="ORD_LINE"."ORDSLN" AND 
              "SHIPMENT_LINE"."WH_ID"="ORD_LINE"."WH_ID" AND "SHIPMENT_LINE"."CLIENT_ID"="ORD_LINE"."CLIENT_ID")
  25 - access("ORD_LINE"."ORDNUM"="ORD"."ORDNUM" AND "ORD_LINE"."WH_ID"="ORD"."WH_ID" AND 
              "ORD_LINE"."CLIENT_ID"="ORD"."CLIENT_ID")
  26 - access("INVSUB"."VC_CTNCOD"="INVSUB_CTNMST"."CTNCOD"(+) AND 
              "INVLOD"."WH_ID"="INVSUB_CTNMST"."WH_ID"(+))
  27 - filter("PRTFTP_DTL"."UOMLVL"(+)=0)
  28 - access("from$_subquery$_016"."QCSJ_C000000001200008"="PRTFTP_DTL"."WH_ID"(+) AND 
              "from$_subquery$_016"."QCSJ_C000000001200012"="PRTFTP_DTL"."PRTNUM"(+) AND 
              "from$_subquery$_016"."QCSJ_C000000001200010"="PRTFTP_DTL"."PRT_CLIENT_ID"(+) AND 
              "from$_subquery$_016"."QCSJ_C000000001200090"="PRTFTP_DTL"."FTPCOD"(+))

过滤掉嵌入的查询(结果缓慢)

select resultset.*
   from (select first_value(ord.stcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_stcust,
                first_value(ord.st_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_st_adr_id,
                first_value(ord.rtcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_rtcust,
                first_value(ord.rt_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_rt_adr_id,
                first_value(ord.btcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_btcust,
                first_value(ord.bt_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_bt_adr_id,
                first_value(ord.brcust ignore nulls) over(partition by shipment.ship_id
                                                           order by ord.ordnum desc range between unbounded preceding
                                                             and unbounded following) as shp_brcust,
                first_value(ord.br_adr_id ignore nulls) over(partition by shipment.ship_id
                                                              order by ord.ordnum desc range between unbounded preceding
                                                                and unbounded following) as shp_br_adr_id,
                invdtl.dtlnum
           from shipment
          inner
           join shipment_line
             on (shipment.ship_id = shipment_line.ship_id)
          inner
           join invdtl
             on (shipment_line.ship_line_id = invdtl.ship_line_id)
          inner
           join invsub
             on (invdtl.subnum = invsub.subnum)
          inner
           join invlod
             on (invsub.lodnum = invlod.lodnum)
          inner
           join ord_line
             on (shipment_line.ordnum = ord_line.ordnum and shipment_line.ordlin = ord_line.ordlin and shipment_line.ordsln = ord_line.ordsln and shipment_line.wh_id = ord_line.wh_id and shipment_line.client_id = ord_line.client_id)
          inner
           join ord
             on (ord_line.ordnum = ord.ordnum and ord_line.wh_id = ord.wh_id and ord_line.client_id = ord.client_id)
           left
           join ctnmst invlod_ctnmst
             on (invlod.vc_ctncod = invlod_ctnmst.ctncod and invlod.wh_id = invlod_ctnmst.wh_id)
           left
           join ctnmst invsub_ctnmst
             on (invsub.vc_ctncod = invsub_ctnmst.ctncod and invlod.wh_id = invsub_ctnmst.wh_id)
           left
           join prtftp_dtl
             on (invdtl.prtnum = prtftp_dtl.prtnum and invdtl.ftpcod = prtftp_dtl.ftpcod and invlod.wh_id = prtftp_dtl.wh_id and invdtl.prt_client_id = prtftp_dtl.prt_client_id and 0 = prtftp_dtl.uomlvl)
          ) resultset where resultset.dtlnum = 'D00000525035'

执行计划过滤嵌入的查询

Plan hash value: 2559978577

--------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name               | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                    |   570K|   216M|       |   105K  (1)| 00:21:09 |
|*  1 |  VIEW                           |                    |   570K|   216M|       |   105K  (1)| 00:21:09 |
|   2 |   WINDOW SORT                   |                    |   570K|   472M|   494M|   105K  (1)| 00:21:09 |
|*  3 |    HASH JOIN RIGHT OUTER        |                    |   570K|   472M|       |  1642   (1)| 00:00:20 |
|*  4 |     TABLE ACCESS FULL           | PRTFTP_DTL         |   645 | 17415 |       |    10   (0)| 00:00:01 |
|   5 |     NESTED LOOPS OUTER          |                    |   401K|   322M|       |  1630   (1)| 00:00:20 |
|   6 |      VIEW                       |                    |   401K|   319M|       |  1627   (1)| 00:00:20 |
|*  7 |       HASH JOIN                 |                    |   401K|   108M|       |  1627   (1)| 00:00:20 |
|   8 |        TABLE ACCESS FULL        | ORD                |  1229 |   105K|       |    16   (0)| 00:00:01 |
|   9 |        NESTED LOOPS             |                    |   401K|    75M|       |  1610   (1)| 00:00:20 |
|* 10 |         HASH JOIN               |                    |   401K|    65M|       |  1606   (1)| 00:00:20 |
|  11 |          INDEX FULL SCAN        | SHIPMENT_PK        |  1161 | 12771 |       |     2   (0)| 00:00:01 |
|* 12 |          HASH JOIN              |                    |   401K|    61M|       |  1603   (1)| 00:00:20 |
|  13 |           VIEW                  | index$_join$_003   |  4523 |   207K|       |    15   (0)| 00:00:01 |
|* 14 |            HASH JOIN            |                    |       |       |       |            |          |
|  15 |             INDEX FAST FULL SCAN| SHIPMENT_LINE_PK   |  4523 |   207K|       |     4   (0)| 00:00:01 |
|  16 |             INDEX FAST FULL SCAN| SHIPMENT_LINE_IDX5 |  4523 |   207K|       |    15   (0)| 00:00:01 |
|  17 |           NESTED LOOPS          |                    |   404K|    43M|       |  1586   (1)| 00:00:20 |
|* 18 |            HASH JOIN            |                    |  7227 |   402K|       |   140   (1)| 00:00:02 |
|  19 |             TABLE ACCESS FULL   | INVSUB             |  7224 |   204K|       |    69   (0)| 00:00:01 |
|  20 |             NESTED LOOPS OUTER  |                    |  8570 |   234K|       |    70   (0)| 00:00:01 |
|  21 |              TABLE ACCESS FULL  | INVLOD             |  8570 |   167K|       |    69   (0)| 00:00:01 |
|* 22 |              INDEX UNIQUE SCAN  | CTNMST_PK          |     1 |     8 |       |     1   (0)| 00:00:01 |
|* 23 |            INDEX RANGE SCAN     | INVDTL_IDX5        |    56 |  3136 |       |     1   (0)| 00:00:01 |
|* 24 |         INDEX UNIQUE SCAN       | ORD_LINE_PK        |     1 |    25 |       |     1   (0)| 00:00:01 |
|* 25 |      INDEX UNIQUE SCAN          | CTNMST_PK          |     1 |     8 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------

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

   1 - filter("RESULTSET"."DTLNUM"='D00000525035')
   3 - access("from$_subquery$_016"."QCSJ_C000000001200010"="PRTFTP_DTL"."PRT_CLIENT_ID"(+) AND 
              "from$_subquery$_016"."QCSJ_C000000001200008"="PRTFTP_DTL"."WH_ID"(+) AND 
              "from$_subquery$_016"."QCSJ_C000000001200090"="PRTFTP_DTL"."FTPCOD"(+) AND 
              "from$_subquery$_016"."QCSJ_C000000001200012"="PRTFTP_DTL"."PRTNUM"(+))
   4 - filter("PRTFTP_DTL"."UOMLVL"(+)=0)
   7 - access("ORD_LINE"."ORDNUM"="ORD"."ORDNUM" AND "ORD_LINE"."WH_ID"="ORD"."WH_ID" AND 
              "ORD_LINE"."CLIENT_ID"="ORD"."CLIENT_ID")
  10 - access("SHIPMENT"."SHIP_ID"="SHIPMENT_LINE"."SHIP_ID")
  12 - access("SHIPMENT_LINE"."SHIP_LINE_ID"="INVDTL"."SHIP_LINE_ID")
  14 - access(ROWID=ROWID)
  18 - access("INVSUB"."LODNUM"="INVLOD"."LODNUM")
  22 - access("INVLOD"."VC_CTNCOD"="INVLOD_CTNMST"."CTNCOD"(+) AND 
              "INVLOD"."WH_ID"="INVLOD_CTNMST"."WH_ID"(+))
  23 - access("INVDTL"."SUBNUM"="INVSUB"."SUBNUM")
  24 - access("SHIPMENT_LINE"."ORDNUM"="ORD_LINE"."ORDNUM" AND 
              "SHIPMENT_LINE"."ORDLIN"="ORD_LINE"."ORDLIN" AND "SHIPMENT_LINE"."ORDSLN"="ORD_LINE"."ORDSLN" AND 
              "SHIPMENT_LINE"."WH_ID"="ORD_LINE"."WH_ID" AND "SHIPMENT_LINE"."CLIENT_ID"="ORD_LINE"."CLIENT_ID")
  25 - access("INVSUB"."VC_CTNCOD"="INVSUB_CTNMST"."CTNCOD"(+) AND 
              "INVLOD"."WH_ID"="INVSUB_CTNMST"."WH_ID"(+))

1 个答案:

答案 0 :(得分:1)

不幸的是,由于您尝试过滤的谓词不是按键分区的一部分,因此Oracle无法在内联视图中从外部查询推送谓词。这是因为分析函数在where子句之后应用,并且更改选择哪些行可能会改变结果。

我知道您说最近添加的示例查询是您实际查询的简化版本,因此我建议的内容可能不适用。但是,我希望您的实际查询仅在货件相关表格上具有分析功能,如果是这种情况,则以下情况应该有效。

由于您的分析函数仅影响货件,shipment_line,ord_line和ord表中的行,为什么不将它们拉到单独的子查询中,然后将其连接回其他表?希望这会大大加快速度 - 例如:


_enable = TEXT
_enable.data = GP:tx_powermail_pi1|field|checkboxmarkername|0
相关问题