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

0    322    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

    您可能还喜欢...

    发表回复