适当采用Histogram 让Oracle达成最优Execution Plan

Production DB, 主要是OLTP和一部分Report。最近由于盘点经常要出一个Report,这个Report会用对List里的COA_ITEM的每个值去捞取资料。但这个Report经常要跑很长时间。

[@more@]

其中一个重要相关SQL如下:

SELECT count(*)

FROM mo_d d, coa_sn_d s

WHERE s.flag = 'Z'

AND d.isn = s.isn

AND d.grp <> 'YYY'

AND s.coa_item = 'XXXXXXXX'

AND s.companyid = 'FFFPC';

ReportDeveloper在搞出这个Report后发现执行时间大大超出预期,有时要1小时才能出全部结果,但检查一些List里的COA_ITEM的值又发现都执行很快。

然后这个问题交到我手上。

在跟Developer了解更多执行情况后,焦点集中到某些COA_ITEM的值上,在执行这些值的时侯,这个SQL通常要10~30分钟才能跑完。

检查了下2TableAnalyze日期,都比较近。 而既然有些快有些慢,那问题就很可能出在Data Skew上。

2Table的资料:

COA_SN_D: 650 0000 rows non-partitioned table

MO_D: rows > 100 000 000rows partitioned table

SQL一般的执行计划:

SQL> SELECT COUNT(*)

2 FROM mo_d d, coa_sn_d s

3 WHERE s.flag = 'C'

4 AND d.isn = s.isn

5 AND d.grp <> 'H01'

6 AND s.coa_item = '15L1-000A0AS'

7 AND s.companyid = 'FFFPC';

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1434 Card=1 Bytes=58

)

1 0 SORT (AGGREGATE)

2 1 TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'MO_D' (Cost=4 C

ard=1 Bytes=21)

3 2 NESTED LOOPS (Cost=1432 Card=1841 Bytes=106778)

4 3 TABLE ACCESS (BY INDEX ROWID) OF 'COA_SN_D' (Cost=11

0 Card=1841 Bytes=68117)

5 4 INDEX (RANGE SCAN) OF 'COA_SN_D4' (NON-UNIQUE) (Co

st=13 Card=2040)

6 3 INDEX (RANGE SCAN) OF 'MO_D1' (UNIQUE) (Cost=3 Card=

1)

Execution Plan显示Join PlanNested Loop.

NLDriving Row sets小的情况下有很好的性能,但在Driving Row sets大的情况下性能却很糟糕。很显然,在某些COA_ITEM的值下,Driving Row sets的实际结果要比CBO预估的要大很多。

在单独对某些COA_ITEM值产生的row sets 进行count(*)的结果表明,数量都是150W以上。

接下来又问了下Developer,最后执行结果多大,得到结果是几千到1万多些行。

面对这样的JOIN情形,最值得采用的无疑就是HASH JOIN了。

强制采用Hash_join:

SQL> SELECT /*+use_hash(s,d)*/COUNT(*)

2 FROM mo_d d, coa_sn_d s

3 WHERE s.flag = 'C'

4 AND d.isn = s.isn

5 AND d.grp <> 'H01'

6 AND s.coa_item = '15G29L100300'

7 AND s.companyid = 'FFFPC';

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=90462 Card=1 Bytes=5

8)

1 0 SORT (AGGREGATE)

2 1 HASH JOIN (Cost=90462 Card=463 Bytes=26854)

3 2 TABLE ACCESS (BY INDEX ROWID) OF 'COA_SN_D' (Cost=31 C

ard=463 Bytes=17131)

4 3 INDEX (RANGE SCAN) OF 'COA_SN_D4' (NON-UNIQUE) (Cost

=6 Card=513)

5 2 PARTITION RANGE (ALL)

6 5 PARTITION HASH (ALL)

7 6 TABLE ACCESS (FULL) OF 'MO_D' (Cost=89982 Card=259

54787 Bytes=545050527)

COST 9W多。

实际执行时间3分钟不到,Consistent Gets远小于NL的方案。

Execution Plan的正确路线有了,下面的问题是怎样让Oracle自己适时的拿来用---给出最正确的Statistics

OLTP那边的程式负责人了解到他们的Package/Procedure/Function等等都没有用到COA_SN_D4这个Index上的Column, 那就放心的搜集Histogram了。

Gather完该Index3ColumnsHistogram( size skewonly)后,Oracle果然在特定的COA_ITEM值上选择了Hash_join.

整个Report的执行时间得以大大缩短。

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

转载于:http://blog.itpub.net/10856805/viewspace-1021131/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值