达梦SQL执行耗时异常问题排查

在系统运行的过程中经常遇到通过客户端在数据库执行SQL语句很快,但是在程序中执行耗时长的问题,针对该类问题我们一般从如下两方面分析:

网络情况排查

需要确认网络上是否存在不稳定的因素,因为程序远程访问数据库后,会获取结果,如果网络不稳定,获取结果耗时可能就会出现不稳定的问题,导致程序获取结果集耗时长。此时可以通过ping命令看下网络是否存在丢包问题或者返回时间过长。可以通过在不同机器上的客户端执行相同的语句来进行判断,存在网络问题的服务器上的耗时长,其他机器上耗时短,一般就可判定是网络问题导致。

计划缓存问题

这个是我们今天关注的重点,数据库默认开启了计划缓存,可以通过如下语句查看是否开启:

 select PARA_NAME,PARA_VALUE  from v$dm_ini  where para_name like 'USE_PLN_POOL';

该参数设置的为非0,即开启了计划缓存。

参数值解释:

0:禁止执行计划的重用;  

1:启用执行计划的重用功能 ;

2:对不包含显式参数的语句进行常量参数化优化;

3:即使包含显式参数的语句也进行常量参数化优化

开启计划缓存功能后,在SQL初次执行后会将对应执行计划存储到缓冲区,下次执行相同的SQL或者常量值不同的SQL会优先从计划缓存池中查找是否存在已缓存计划,这样可以减少语句分析优化过程,提高执行效率。当计划缓存池满了,根据LRU算法进行计划的淘汰。通过如下语句可以查询计划缓存的情况:​​​​​​​

--获取sql的计划缓存select cache_item,sqlstr from v$cachepln where sqlstr like '%SQL语句%';
查询到对应的语句的计划缓存信息后,通过如下命令生成语句计划到本地文件:
alter session set events 'immediate trace name plndump level 查出的cache_item,dump_file ''/dbdata/plan0415.log''';

注:其中的文件路径需要单引号引起,由于路径是在外层单引号内,所以使用单引号做了转义,两个单引号代表一个单引号。

根据获取到的计划,我们可以确认计划是否准确,如果计划缓存中的计划存在问题,那后续的SQL在缓存中找到对应的计划后依然使用执行效率不高的计划。如果相关计划一直没有被淘汰,就有可能出现程序执行耗时很长的问题。

那为什么在达梦管理工具中执行时,速度就很快呢?这是因为SQL语句在执行后,在进行计划缓存匹配时,是严格按照执行SQL的字符进行匹配的。数据库会对执行的SQL生成对应的哈希值,SQL语句多一个空格,对于优化器来说都是不同的SQL,这就出现了上述描述的问题。

当遇到该种问题时,我们可以尝试清理计划缓存来丢弃执行效率不高的计划,然后让优化器根据最新的统计信息生成新的执行计划,清理的方法如下:​​​​​​​

--清理计划缓存call SP_CLEAR_PLAN_CACHE(cache_item);

清理完毕后,可以通过程序确认对应的操作执行效率是否正常。

例-构造数据:​​​​​​​

create table test(c1 int, c2 varchar(100), c3 int, primary key(c1));  begin   for i in 1..100000 loop      insert into test values(i, 'aaaaaaa', i);    end loop;   commit;end;

执行查询语句:

select * from test where c3=3;

查看执行计划缓存​​​​​​​

select cache_item,sqlstr from v$cachepln where sqlstr like '%select * from test where c3=3%';

生成计划缓存中的执行计划:

alter session set events 'immediate trace name plndump level 848533592,dump_file ''/dbdata/plan0427.log''';

查看生成的文件/dbdata/plan0427.log​​​​​​​

DM Database Server x64 V8 *** 2021-04-27 16:32:42.803000*** start dump the infos of pln[848533592].start dump the infos of pln[848533592].SQL_STR:select * from test where c3=3;PLN_CMD:0savepoint6dop_try_begin010dop_try_begin014sql 0 024nop26jmp6732nop34push040swap42sloc146err_set 050rollback56jmp6762nop64throw dir167exception end69savepoint75cop 'b'79hlt 0 sqlnode[0]::::1   #NSET2: [12, 2500, 64]2     #PRJT2: [12, 2500, 64]; exp_num(4), is_atom(FALSE)3       #SLCT2: [12, 2500, 64];4         #CSCN2: [12, 100000, 64]; INDEX33555613(TEST)end dump the infos of pln[848533592].

在文件中的最后一部分我们可以看到语句实际执行时的执行计划。如果需要手动淘汰该计划,执行如下SQL:

call SP_CLEAR_PLAN_CACHE(848533592);

再次查询计划缓存时,该计划缓存已经淘汰。

小结

数据库为什么在计划缓存中生成了非最优的计划呢?达梦数据库的优化器是基于代价的优化器,精确的统计信息有助于CBO生成更优的计划,但是统计信息并不会实时更新。所以,统计信息的不准确,就导致CBO生成了非最优的计划。统计信息只有在我们手动更新的时候才会生成,所以当我们发现一些业务表的相关语句存在因为数据的变化而导致语句执行效率差异变大时,我们可以通过设定定时作业对表进行统计信息的收集。

在DM8的新版本中,已经支持了DBMS_STATS. SET_TABLE_PREFS方法,通过开启INI参数AUTO_STAT_OBJ来监控用户表的增删改行数,利用DBMS_STATS系统包中SET_TABLE_PREFS方法对表进行设定,然后利用事件触发器完成自动更新表统计信息的功能。这部分在后面找机会向大家介绍。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值