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

干货攻略|达梦SQL执行耗时异常问题排查

达梦大学 2021-04-29
3576

/ 这是我的第208篇文章

达梦干货攻略

【Date:2021.04.28】

MY ARTICLE

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

本章内容已在如下环境上测试:
数据库:达梦数据库DM8;

GAN HUO

网络情况排查


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




GAN HUO

计划缓存问题


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

     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:
                    0savepoint
                    6dop_try_begin0
                    10dop_try_begin0
                    14sql 0 0
                    24nop
                    26jmp67
                    32nop
                    34push0
                    40swap
                    42sloc1
                    46err_set 0
                    50rollback
                    56jmp67
                    62nop
                    64throw dir1
                    67exception end
                    69savepoint
                    75cop '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);

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



                      GAN HUO

                      小结


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

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



                      好,以上是本次分享内容,希望能给大家带来帮助。

                      往期回顾

                      干货丨达梦数据库动态增加实时备库

                      干货丨DM JOB作业的邮件发送

                      DCA开班丨在线培训招生(2021年5月17日-19日)

                      DCP开班丨在线培训招生(2021年5月24日-27日)

                      公开课DEM搭建与配置解析(直播时间:2021年4月29日)


                      关注我们
                      微信号DaMeng-University
                      QQ2908982381 

                      END


                      【内容】:吴聪

                      【审核】:青城

                      【编辑】:王

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

                      评论