Join Predicate Push-Down

1.定义

The join predicate pushdown (JPPD) transformation allows a view to be joined with index-based nested-loop join method, which may provide a more optimal alternative. In the join predicate pushdown transformation, the view remains a separate query block, but it contains the join predicate, which is pushed down from its containing query block into the view. The view thus becomes correlated and must be evaluated for each row of the outer query block. These pushed-down join predicates, once inside the view, open up new index access paths on the base tables inside the view; this allows the view to be joined with index-based nested-loop join method, thereby enabling the optimizer to select an efficient execution plan.

At the first step, Oracle tries to merge the view. This is called  view merging . When the view merging is not possible, Oracle tries to push the predicates into the view. Oracle pushes not only simple predicates, but also join predicates.  PUSH_PRED  hint controls the join predicate pushing.

2.分类

JPPD - join predicate push-down            
OJPPD - old-style (non-cost-based) JPPD

1)JPPD:

10gR2之后,jppd是基于cost的,不仅需要满足_push_join_predicate=true和连接的视图满足_optimizer_extend_jppd_view_types的类型,且转换后cost要小于不转换的cost。

2)OJPPD

10gR2之前,jppd是启发式转换,现在叫ojppd,也就是不计成本的。10gR2后如果要启用OJPPD,需要关闭_optimizer_cost_based_transformation或者_optimizer_push_pred_cost_based

3.参数

KSPPINM                        KSPPSTVL   KSPPDESC
------------------------------ ---------- ------------------------------------------------------------
_push_join_predicate           TRUE       enable pushing join predicate inside a view

hint:push_pred/no_push_pred

4.限制

KSPPINM                            KSPPSTVL     KSPPDESC
------------------------------    ----------   ------------------------------------------------------------
_optimizer_extend_jppd_view_types   TRUE       join pred pushdown on group-by, distinct, semi-/anti-joined view
                                       
即视图需要满足:
  • UNION ALL/UNION view
  • Outer-joined view
  • Anti-joined view
  • Semi-joined view
  • DISTINCT view
  • GROUP-BY view


5.测试

sql文本:

  1. SELECT /*+ qb_name(sb)*/
  2.       t.a, v.object_name, v.object_type
  3.   FROM t,
  4.        (SELECT /*+ qb_name(nb)*/* FROM lxy
  5.         UNION ALL
  6.         SELECT * FROM lxy_1) v
  7.  WHERE t.a = v.object_id;
由于视图带有union all,所以不能做视图合并,但是满足了JPPD的条件

执行计划:

----------------------------------------------------------------------------------------
| Id  | Operation                      | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |       |    20 |  1900 |    42   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                  |       |    20 |  1900 |    42   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL            | T     |    10 |   130 |     2   (0)| 00:00:01 |
|   3 |   VIEW                         |       |     1 |    82 |     4   (0)| 00:00:01 |
|   4 |    UNION ALL PUSHED PREDICATE  |       |       |       |            |          |
|   5 |     TABLE ACCESS BY INDEX ROWID| LXY   |     1 |    31 |     2   (0)| 00:00:01 |
|*  6 |      INDEX RANGE SCAN          | I1    |     1 |       |     1   (0)| 00:00:01 |
|   7 |     TABLE ACCESS BY INDEX ROWID| LXY_1 |     1 |    31 |     2   (0)| 00:00:01 |
|*  8 |      INDEX RANGE SCAN          | I2    |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SB
   2 - SB           / T@SB
   3 - SET$5715CE2E / V@SB
   4 - SET$5715CE2E
   5 - SEL$E32B9D82 / LXY@NB
   6 - SEL$E32B9D82 / LXY@NB
   7 - SEL$9113C594 / LXY_1@SEL$1
   8 - SEL$9113C594 / LXY_1@SEL$1
Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      INDEX_RS_ASC(@"SEL$E32B9D82" "LXY"@"NB" ("LXY"."OBJECT_ID"))
      INDEX_RS_ASC(@"SEL$9113C594" "LXY_1"@"SEL$1" ("LXY_1"."OBJECT_ID"))
      USE_NL(@"SB" "V"@"SB")
      LEADING(@"SB" "T"@"SB" "V"@"SB")
      NO_ACCESS(@"SB" "V"@"SB")
      FULL(@"SB" "T"@"SB")
      OUTLINE(@"SB")
      OUTLINE(@"SET$1")
      OUTLINE(@"SEL$1")
      OUTLINE(@"NB")
      OUTLINE_LEAF(@"SB")
      PUSH_PRED(@"SB" "V"@"SB" 1)
      OUTLINE_LEAF(@"SET$5715CE2E")
      OUTLINE_LEAF(@"SEL$9113C594")
      OUTLINE_LEAF(@"SEL$E32B9D82")
      ALL_ROWS
      DB_VERSION('11.2.0.4')
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
Predicate Information (identified by operation id):
---------------------------------------------------
   6 - access("LXY"."OBJECT_ID"="T"."A")
   8 - access("LXY_1"."OBJECT_ID"="T"."A")

很明显,CBO对该sql做了视图合并,从10053可以看到更详细的信息

10053:

首先检查到可以对该视图做JPPD:
***********************************
Cost-Based Join Predicate Push-down
***********************************
JPPD: Checking validity of push-down in query block SB (#1)
JPPD:   Checking validity of push-down from query block SB (#1) to query block SET$1 (#2)
JPPD:     Passed validity checks
JPPD: JPPD:   Pushdown from query block SB (#1) passed validity checks.
Join-Predicate push-down on query block SB (#1)
JPPD: Using search type: linear
JPPD: Considering join predicate push-down

1)未做jppd的情况:

JPPD: Starting iteration 1, state space = (2) : (0)
JPPD: Performing join predicate push-down (no transformation phase) from query block SB (#1) to query block SET$1 (#2)
...
JPPD: Updated best state, Cost = 106.38
验证一下不对sql做jppd的cost:

  1. select /*+ qb_name(sb) no_push_pred(v)*/t.a,v.object_name,v.object_type from t,(select /*+ qb_name(nb)*/* from lxy union all select * from lxy_1) v
  2. where t.a=v.object_id;
------------------------------------------------------------------------------
| Id  | Operation            | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |       |    20 |  2060 |   106   (0)| 00:00:02 |
|*  1 |  HASH JOIN           |       |    20 |  2060 |   106   (0)| 00:00:02 |
|   2 |   TABLE ACCESS FULL  | T     |    10 |   130 |     2   (0)| 00:00:01 |
|   3 |   VIEW               |       | 28488 |  2503K|   104   (0)| 00:00:02 |
|   4 |    UNION-ALL         |       |       |       |            |          |
|   5 |     TABLE ACCESS FULL| LXY   | 14243 |   431K|    52   (0)| 00:00:01 |
|   6 |     TABLE ACCESS FULL| LXY_1 | 14245 |   431K|    52   (0)| 00:00:01 |
------------------------------------------------------------------------------

2)jppd转换后的情况

JPPD: Starting iteration 2, state space = (2) : (1)
JPPD: Performing join predicate push-down (candidate phase) from query block SB (#1) to query block SET$1 (#2)
JPPD:   Pushing predicate "T"."A"="V"."OBJECT_ID"
 from query block SB (#1) to query block SET$1 (#2)
JPPD: Push dest of pred 0x8a74b4a8 is qb 0x8a74dff0:query block SET$1 (#2)
JPPD: Push dest of pred 0x8a4d3f98 is qb 0x8a74dff0:query block SET$1 (#2)
...
JPPD: Updated best state, Cost = 42.01

3)确定转换

JPPD: Will use JPPD from SB (#1) to SET$1 (#2).  --由于转换后cost仅为42所以确定转换


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31347199/viewspace-2121619/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/31347199/viewspace-2121619/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值