暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 统计信息不正确引发的案例

bestpaydata 2021-04-18
2294


案例分析总结:

sql优化的四点:

1、对象的进入方式

2、对象的关联方式

3、每一步的代价与基数

4、执行计划的注释部分

该案例是由于对象的统计信息收集有误,而导致sql执行使用错误的执行计划。

因此统计信息的及时收集,正确的收集,对sql的运行是灰常重要的。

对于直方图统计信息的收集,我们的建议是:

若之前有直方图信息,则继续收集,若没有就不要多余的收集直方图信息(按照默认就好),除非可以证明有直方图信息更好。


案例分析过程:


DBA发现一条sql执行了超长时间,还有没执行完(超过10小时),经分析该sql是一个定时job每天凌晨5点执行存储过程发起的。

sql及试图定义不再提供,我们只关注核心部分。

6m37jw4kj0XXX:

Plan hash value: 2496417X94


基于表上的索引信息:


相关的统计信息:


sql那么长,其实我们只用看 核心部分:

select * from (SELECT CUXXXXXX_NO,

REVSAL_FLAG,

CANCEL_FLAG,

SXXXXX_DATE,

TXX_TXXX,

TXX_AMT,

TXX_CHANNEL,

(CASE

WHEN H.CUSXXXXX_CITY_COXX IN ('999900', '999901') THEN

'999901'

ELSE

CUSXXXXX_CITY_COXX

END) CUSXXXXX_CITY_COXX

FROM V_TXX_LXX_HIS H) A

WHERE A.CANCEL_FLAG IS NULL

AND A.CUSXXXXX_CITY_COXX IS NOT NULL

AND A.REVSAL_FLAG IS NULL

AND A.CUXXXXXX_NO LIKE '86%'

AND A.SXXXXX_DATE = '20151120';

执行计划:2497803424:


在上面的执行计划里面,我们看到4后 优化器估算的基数为9009;

实际呢:

SELECT count(*) FROM T_XXX_XXXX_XX_HIS t where CUXXXXXX_NO LIKE '86%'; --44914604

(到此我们可以猜测是统计信息的问题)

为什么没有用到这个索引I_OXX_XXX_SXXX:

SELECT count(*) FROM T_XXX_XXXX_XX_HIS a where A.SXXXXX_DATE = '20151120';--3701210


强制使用:

select *+ index(a I_OXX_XXX_SXXX)*/ count(*)

from T_XXX_XXXX_XX_HIS a

where CUXXXXXX_NO LIKE '86%'

AND CASE "CUSXXXXX_CITY_COXX"

WHEN '999900' THEN

'999901'

WHEN '999901' THEN

'999901'

ELSE

"CUSXXXXX_CITY_COXX"

END IS NOT NULL

AND CANCEL_FLAG IS NULL

AND REVSAL_FLAG IS NULL

AND SXXXXX_DATE = '20151120';


于是对统计信息重新收集:

begin

DBMS_STATS.GATHER_TABLE_STATS ('BTUPXXXXXX','T_XXX_XXXX_XX_HIS',degree=>8);

end;

现在执行:

select * from (SELECT CUXXXXXX_NO,

REVSAL_FLAG,

CANCEL_FLAG,

SXXXXX_DATE,

TXX_TXXX,

TXX_AMT,

TXX_CHANNEL,

(CASE

WHEN H.CUSXXXXX_CITY_COXX IN ('999900', '999901') THEN

'999901'

ELSE

CUSXXXXX_CITY_COXX

END) CUSXXXXX_CITY_COXX

FROM V_TXX_LXX_HIS H) A

WHERE A.CANCEL_FLAG IS NULL

AND A.CUSXXXXX_CITY_COXX IS NOT NULL

AND A.REVSAL_FLAG IS NULL

AND A.CUXXXXXX_NO LIKE '86%'

AND A.SXXXXX_DATE = '20151120';


若还按照之前的执行计划:



现在的统计信息:


我们可以发现新收集的统计信息与旧的相比:1: 数据量不对 2:直方图信息也不对

于是继续做下面的实验:(排除直方图的影响)

begin

DBMS_STATS.GATHER_TABLE_STATS ('BTUPXXXXXX','T_XXX_XXXX_XX_HIS',degree=>8,method_opt=>'for columns SXXXXX_DATE size 1 CUXXXXXX_NO size 1');

end;

再执行:


===============================================================================

对比这3个执行计划:



再启动job:观察



因此统计信息的及时收集,正确的收集,对sql的运行是灰常重要的。

对于直方图统计信息的收集,我们的建议是:

若之前有直方图信息,则继续收集,若没有就不要多余的收集直方图信息(按照默认就好),除非可以证明有直方图信息更好





文章转载自bestpaydata,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论