pbe功能导致执行计划错误
原作者:陈鋆
某客户在mogdb505版本情况下,通过JDBC调用prepareStatement时,发现sql执行计划出现问题,但是在jdbc环境中调整limit个数,随着limit个数增加,导致执行就会很卡,当limit个数小于10时,执行时间正常,且通过jdbc查看执行计划,发现也走了正常的执行计划。


sql文本如下:
select *
from (
select t.txn_no
from t_cnaps_txn_flow t
left join t_hvps_txn_sub c on t.txn_no = c.txn_no
where t.work_date >= $1
and t.work_date <= $2
and t.trans_orgid = $3
order by t.txn_no desc
) xsql_t
limit 30 offset 0
索引信息如下:

通过gstrace采集sql执行信息,在卡的时候发现sql走了最差的索引:

说明在这种使用传输参数的过程中,数据库中该sql生成了一个错误的执行计划,关注该功能为pbe的功能,该功能是类似于oracle绑定变量的功能,通过pbe方式执行的sql,优化器会基于规则、代价、参数等因素选择生成Custom Plan或Generic Plan执行。用户可以通过use_cplan/use_gplan的hint指定使用哪种计划执行方式。https://www.modb.pro/db/1760502447508377600
在该环境下,pbe的功能明显选择了错误的执行计划,然后关闭了pbe功能,将参数enable_pbe_optimization设置为off,然后业务环境恢复正常。
出现了正确得执行计划:

继续分析该执行计划,在limit过滤条件多了后,数据库依然会选择全表扫描,导致运行缓慢,继续分析执行过程,该执行计划使用了主键索引,也就是直接通过扫描主键,然后过滤出来数据进行filter回表,只过滤limit的限制直接返回给客户端,当limit条数过多后,优化器会认为全表扫描的代价更低,所以选择了全表扫描的执行计划。

进一步分析,由于整体选择条件筛选出来的条件较少,是否可以通过索引扫描出来全部需要的列后进行排序。通过该方式,对该表创建组合索引(trans_orgid,work_date,txn_no),这样避免回表,通过该优化后,无论limit选择任何的值,都能通过索引去取,优化到1ms

总结:pbe功能为社区开发的功能,目前并不完善,因此开启只是在POC的情况下开启,开功能可能会导致执行计划出现问题,而且选择错误的执行计划,该功能通过源码看,如果关闭该功能,大量短连接执行和大量并发的情况下可可能会导致内存异常增加。

mogdb数据库




