笛卡尔乘积 oracle,【优化案例】一次笛卡尔乘积的优化

今天一个网友妹子发来一段SQL说执行非常慢,让我看下,其实问题很简单,2分钟搞定,我们平时也会经常遇到,SQL及执行计划如下--跑了7分钟

SELECT T.*, A.*, B.LOGIN_ID, B.USER_NAME

FROM MID.T_RPT_RES_PRO_PRE_ALL_LISTTEMP T,

KPICODE.ODS_CB_ORGAN_GRID_ALL_MV A,

KPI.PURE_USER B

WHERE T.FIVE_LEVEL_OWN = B.LOGIN_ID

AND B.USER_ORG = A.LEVEL_ID;

SELECT COUNT(1) FROM MID.T_RPT_RES_PRO_PRE_ALL_LISTTEMP T; --4733

SELECT COUNT(1) FROM KPICODE.ODS_CB_ORGAN_GRID_ALL_MV A; --16719

SELECT COUNT(1) FROM KPI.PURE_USER B; --26497

执行计划

----------------------------------------------------------

Plan hash value: 2012136974

--------------------------------------------------------------------------------

-------------------------------

| Id | Operation | Name | Rows |

Bytes | Cost (%CPU)| Time |

--------------------------------------------------------------------------------

-------------------------------

| 0 | SELECT STATEMENT | | 1 |

1259 | 144 (1)| 00:00:02 |

| 1 | NESTED LOOPS | | 1 |

1259 | 144 (1)| 00:00:02 |

| 2 | MERGE JOIN CARTESIAN | | 1 |

1236 | 144 (1)| 00:00:02 |

| 3 | TABLE ACCESS FULL | T_RPT_RES_PRO_PRE_ALL_LISTTEMP | 1 |

1138 | 2 (0)| 00:00:01 |

| 4 | BUFFER SORT | | 16690 |

1597K| 142 (1)| 00:00:02 |

| 5 | MAT_VIEW ACCESS FULL | ODS_CB_ORGAN_GRID_ALL_MV | 16690 |

1597K| 142 (1)| 00:00:02 |

|* 6 | TABLE ACCESS BY INDEX ROWID| PURE_USER | 1 |

23 | 0 (0)| 00:00:01 |

|* 7 | INDEX UNIQUE SCAN | UK_PURE_USER_LOGIN_ID | 1 |

| 0 (0)| 00:00:01 |

--------------------------------------------------------------------------------

-------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

6 - filter("B"."USER_ORG"="A"."LEVEL_ID")

7 - access("T"."FIVE_LEVEL_OWN"="B"."LOGIN_ID")

统计信息

----------------------------------------------------------

1 recursive calls

0 db block gets

177858134 consistent gets

0 physical reads

0 redo size

1436253 bytes sent via SQL*Net to client

2157 bytes received via SQL*Net from client

276 SQL*Net roundtrips to/from client

1 sorts (memory)

0 sorts (disk)

4125 rows processed

可以看到2个表和一个物化视图关联,数据量都不大(几万条数据),却执行了7分钟,1.7亿的逻辑读!!

看下执行计划,ID=2的MERGE JOIN CARTESIAN,

看到这个就基本明白怎么回事了,MERGE JOIN CARTESIAN是笛卡尔乘积的意思,这样的一个SQL里为什么会出现笛卡尔积呢?

看下where条件FROM MID.T_RPT_RES_PRO_PRE_ALL_LISTTEMP T,

KPICODE.ODS_CB_ORGAN_GRID_ALL_MV   A,

KPI.PURE_USER                      B

WHERE T.FIVE_LEVEL_OWN = B.LOGIN_ID

AND B.USER_ORG = A.LEVEL_ID;

3表关联T和B关联,然后B和A关联,没有漏关联条件,而走了笛卡尔积。我们可以看到是T表和A表做了笛卡尔积,再跟B表做了NL

然而关联条件确实T和B关联 B和A关联,T和A并没有直接的关联关系,

所以可以看出这里CBO错误的评估让T和A没有关联关系的表先做了关联,当然产生了笛卡尔积,想解决这个问题也很简单,

加hint让执行计划按照我想要的路径走,use_hash(T,B,A)即可,改后秒出数据。

止于为什么Oracle会选择走这样的执行计划,可以说是Oracle的一个BUG,错误的评估导致了没有关联的表关联了起来。

有人说在10gR2版本此bug已经修复,但是仍旧经常出现这个问题,所以大家如果遇到此问题可以直接指定执行路径即可。

还有人说可以直接修改当前session禁用笛卡尔积,使用/*+ OPT_PARAM('_optimizer_mjc_enabled','false') */,于是我也让妹子试了试发现依旧很慢,

我看了下执行计划,执行计划中虽然去掉了笛卡尔积,但路径没有改变,依旧是T和A先关联,不过使用的是NL关联。所以依旧很慢

fddb33e52169f24bb3cd1b7f2ffbd35d.jpg

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值