关键字:
KingbaseES、JDBC、客户端缓存、人大金仓
背景描述
在数据库应用中,相同语句的频繁执行较为常见,为了提高此类语句执行的效率,普遍的策略是提供预编译语句缓存功能,如Oracle和MySQL等数据库均是采用这种方法。主要是在客户端维护一个缓存队列,采用最近最少使用算法LRU(Least Recently Used),并新增一个Hash表来优化结构,以实现快速查找,这通常使用LinkedHashMap来构建。但是,在实际应用中,可能存在周期性语句执行,导致缓存失效,以及低频率执行的语句将高频率执行的语句推出的缓存污染问题。
功能设计
Kingbase-JDBC同样采用LRU算法实现缓存队列,在队列成员中添加了执行次数标记变量,客户端新增prepareThreshold参数,此参数可用于动态控制语句对象缓存规则,适应多种不同的应用场景;新增preferQueryMode参数,用于指定使用哪种模式发送查询给数据库;新增preparedStatementCacheQueries参数,用于指定语句最大缓存数目;新增preparedStatementCacheSizeMiB参数,用于指定语句最大缓存大小。
图1展示了客户端语句对象缓存功能的执行流程。用户根据使用需求,初始化参数prepareThreshold、preparedStatementCacheSizeMiB、preferQueryMode和preparedStatementCacheQueries。随后每次创建语句对象,都去缓存中查询此对象是否有缓存,若否,则根据语句对象创建Key值,然后解析语句并创建缓存语句对象;若是,则直接获取缓存语句对象。接着判断此对象执行次数+1是否大于等于prepareThreshold,若否,则直接进入语句执行模块;若是,则开启使用服务器端缓存,并执行语句。在语句执行完毕,并关闭语句对象时,在缓存中添加或更新此对象,将其执行次数增加1。若业务还有下一条命令需执行,则循环上述流程。
通过设置prepareThreshold的值,可以避免大部分周期性语句执行导致的缓存失效问题,但热点语句场景下的缓存污染问题并不能避免。可能的解决缓存污染的方法是,将缓存对象中的语句执行次数变量纳入到缓存淘汰的考量当中,若当前语句的执行次数较高,则将其执行次数修改为较低值,并重新放入缓存队列,以达到延迟淘汰的效果。
技术效果
图2显示了不同缓存功能设置,在热点语句执行场景下的执行时间对比结果,其中,有缓存设置的prepareThreshold等于1。可以发现,相比于无缓存功能,有缓存功能时,语句执行的效率更高,即使缓存失效,也依然显示出有利的结果。随着执行语句条数的增多,无缓存功能时,语句执行用时迅速上升,而有缓存功能时,语句执行用时的上升趋势相对缓慢。
参考文档:
无