统计信息不准确导致执行计划走了笛卡尔积

0    390    2

Tags:

👉 本文共约3585个字,系统预计阅读时间或需14分钟。

昨天有事没有上班,今天早上来查看系统的时候发现了很多笛卡尔积的sql,而且一直在跑,已经运行了10多个小时了,觉得这个比较典型,这里记录一下:

SELECT a.ELAPSED_TIME 已运行时间,a.MONITOR_TYPES,a.SQL_ID,a.SQL_TEXT

FROM XT_SQL_RUBBISH_MONITOR_LHR a

WHERE a.MONITOR_TYPES = '笛卡尔积监控'

and a.ID>=45150

ORDER BY a.IN_DATE DESC;

img

截取了其中一个sql:

--create table czh_temp_1312_t6 nologging as

SELECT a.CUST_TYPE_V1,

a.CUST_TYPE_V2,

a.CUST_TYPE_V3,

a.CURRENT_FLAG,

a.ACTIVE_FLAG,

a.ACTIVE2_FLAG,

a.BSCORE_SEG,

b.month_stamp,

b.DELQ_LEVEL,

SUM(b.real_dual_bal + nvl(b.inst_rmb_unposting_amt,

0)) AS AR,

SUM((c.LAST_6M_INT 2 + c.LAST_6M_CHARGEFEE 2 +

c.LAST_6M_OVERLIMIT_FEE 2 + c.LAST_6M_CA_FEE 2 +

c.LAST_6M_INST_FEE 2 - c.LAST_6M_COST_OF_BAL 2 -

c.LAST_6M_COST_OF_INST * 2 -

c.pd * (c.last_6m_bal_avg + c.last_6m_inst_avg))) AS roa_fz,

SUM((c.last_6m_bal_avg + c.last_6m_inst_avg)) AS roa_fm

FROM czh_new_dist_1312 a,

riskrept.rko_acct_snap_his PARTITION(P201406) b,

riskdw.crlimset_roa_his PARTITION(P201406) c

WHERE a.delq_level = '0'

AND a.acct = b.acct

AND a.acct = c.acct

GROUP BY a.CUST_TYPE_V1,

a.CUST_TYPE_V2,

a.CUST_TYPE_V3,

a.CURRENT_FLAG,

a.ACTIVE_FLAG,

a.ACTIVE2_FLAG,

a.BSCORE_SEG,

b.month_stamp,

b.DELQ_LEVEL

ORDER BY a.CUST_TYPE_V1,

a.CUST_TYPE_V2,

a.CUST_TYPE_V3,

a.CURRENT_FLAG,

a.ACTIVE_FLAG,

a.ACTIVE2_FLAG,

a.BSCORE_SEG,

b.month_stamp,

b.DELQ_LEVEL;

其他3个sql都是一样的,只是表a变了,

img

大概看了一下几个sql语句,涉及到的都是同几个表,所以这里列出其中一个执行计划,查看sqlid为5r911ty8dnkwk的sql在内存中的执行计划:

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('5r911ty8dnkwk',0,'advanced'));

img

这里典型的是rows都为1,可以大胆揣测是统计信息有问题导致sql的执行计划走了笛卡尔积的连接了,有关这个rows还有一个例子在我的blog上,连接如下:,另外从执行计划可以看出2个分区表,第一个分区表是RKO_ACCT_SNAP_HIS,是第90个分区统计信息有问题,第二个分区表是CRLIMSET_ROA_HIS,是第54个分区的统计信息有问题,

好吧,我们先看一下第一个表的相关分区的统计信息:

SELECT v.TABLE_NAME,

v.partitioning_type,

v.PARTITION_NAME,

v.partition_size,

v.LAST_ANALYZED,

v.NUM_ROWS,

v.BLOCKS,

v.HIGH_VALUE2

FROM VW_TABLE_PART_LHR V

WHERE V.TABLE_NAME = 'RKO_ACCT_SNAP_HIS'

AND v.PARTITION_POSITION >= 85;

img

由图可以看出6月和7月的分区分别为13G和14G,但是统计行数却为0,另外分析时间可以看出是13年6月的,这个很老了的,,,,,好吧,分别运行如下脚本收集这2个分区的统计信息,当然对于当前脚本我们只需要分析6月这个分区即可,但是发现问题了就一并解决了呗:

BEGIN

dbms_stats.gather_table_stats('RISKREPT',

'RKO_ACCT_SNAP_HIS',

partname => 'P201406',

cascade => TRUE,

granularity => 'PARTITION',

degree => 8);

END;

BEGIN

dbms_stats.gather_table_stats('RISKREPT',

'RKO_ACCT_SNAP_HIS',

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信dbaup66,谢谢!
AiDBA后续精彩内容已被站长无情隐藏,请输入验证码解锁本文!
验证码:
获取验证码: 请先关注本站微信公众号,然后回复“验证码”,获取验证码。在微信里搜索“AiDBA”或者“dbaup6”或者微信扫描右侧二维码都可以关注本站微信公众号。

标签:

Avatar photo

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复