我正在尝试构建一个具有两个级别的复杂查询(一个父查询具有嵌套查询)。在一个非常低的水平我有这样的事情:
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"(+))
答案 0 :(得分:1)
不幸的是,由于您尝试过滤的谓词不是按键分区的一部分,因此Oracle无法在内联视图中从外部查询推送谓词。这是因为分析函数在where子句之后应用,并且更改选择哪些行可能会改变结果。
我知道您说最近添加的示例查询是您实际查询的简化版本,因此我建议的内容可能不适用。但是,我希望您的实际查询仅在货件相关表格上具有分析功能,如果是这种情况,则以下情况应该有效。
由于您的分析函数仅影响货件,shipment_line,ord_line和ord表中的行,为什么不将它们拉到单独的子查询中,然后将其连接回其他表?希望这会大大加快速度 - 例如:
_enable = TEXT
_enable.data = GP:tx_powermail_pi1|field|checkboxmarkername|0