一
前言
开发逻辑总会涉及到访问数据库表内容. 基于性能的考虑,在S4/HANA中尽量把数据逻辑下沉到数据库中.对于一些无法避免的数据库访问,则考虑通过缓存访问,减少和数据库的交互,即便是HANA内存数据库. 缓存也是优化性能的常用方式
本文主要讨论系统中常用的一些缓存方式及相关注意事项
二
思维导图
针对缓存方式总结的思维导图
三
缓存类型
单记录缓存
每次对于读取的关键字进行缓存,以便加速后续再次读取该关键字.
通用区域缓存
多主键的表,比如MARC ,主键 MATNR ,WERKS 读取任一物料: M01,W001 时, 系统缓存 M01的所有地点数据, 以便加速读取该物料的其它地点
完全缓存(全表缓存)
读取表的任何一条记录, 系统缓存该表的所有记录,以便加速下次读取其它记录(适用于记录数较少的配置表)
四
表的缓存
表的缓存通过技术设置实现
其中通用区域缓存,通过设置键值字段数来确定,依赖于键值的顺序,有一定的局限性
单个记录缓存
通用区域缓存
完全缓存
五
相关知识点
ST02(设置/调谐缓冲). SAP缓存有很多类型. 表内容缓存只是其中一项
缓存的相关参数设置:表缓存的整体容量受限于实际应用服务器的内存及缓存参数. 超出参数值后,部分缓存会被清空,以便新的缓存占用.
ST02显示的内容
表读取缓存相关参数
表缓存的详细信息
特定表的缓存信息
六
CDS视图的缓存
貌似只有entities类型的CDS视图才能创建缓存. 需要缓存的视图添加下面的语句标记是否需要启用缓存,其它CDS视图也能缓存,方式不同
@AbapCatalog.entityBuffer.definitionAllowed: true|false
CDS ENTITY BUFFER类型
创建ENTITY的CDS视图及缓存的过程
创建视图,视图中指定缓存属性
创建缓存,指定缓存方式
创建好的对象清单
七
通过程序实现缓存
根据实现的方式,可以分成以下几种
在程序中实现,
在函数中实现
在类中实现
类实现动态缓存
所有代码实现缓存的方式大同小异,下面给出一个函数实现全表缓存的简单逻辑:
在函数中实现全表缓存的实例.
通过全局结构标记该表是否已经缓存, 如果未缓存, 则读取数据缓存在全局哈希表中. 然后再从哈希表中根据主键读取数据
单记录缓存实现逻辑
两个全局哈希内表 MT_ZTTS_H (存放命中的记录) MT_ZTTS_H_MISS(存放数据库中没有的查询记录,避免反复查询) . 优先从MT_ZTTS_H中获取数据, 如果没有获取, 再次读取MT_ZTTS_H_MISS ,如果没有获取, 从数据库读取, 此时判断读取成功, 写入 MT_ZTTS_H . 读取识别,写入MT_ZTTS_H_MISS中.
八
通用的动态类缓存
因为每个需要缓存的表都需要写上述代码. 为了简化开发, 尝试通过类方法动态构建表的缓存并访问
实现方式如下:
全局哈希表MT_ANY,以表名为主键,
缓存表内容,表结构,主键结构, 单记录读取的where条件,不存在记录内容等信息.
根据传入的表, 查询MT_ANY,
如果不存在, 动态定义哈希内表.全量读取数据(全表缓存)
动态读取哈希内表, 获取返回数据.
如果读取不到, 动态SQL查询记录并写入哈希内表中(单记录缓存).
调用方法指定表名,缓存方式,关键字
根据访问方式调用不同的方法,
九
各种缓存方式的性能比较
全表缓存性能比较性能
比较程序 : ZTS_BUFFER_READ
循环1000次
循环1000次
单记录缓存性能比较
读取1000次读取10000次
十
性能比较分析
读取无缓存的表性能肯定最差,实测也是如此, 即使是HANA内存数据库, 不管用什么方式缓存,性能都好于读取无缓存的表
通过表的技术设置和CDS的缓存设置 在大量数据(10000)次方式时,二者性能差异不大. 可以作为不调整代码优化程序性能的主要实现方式(具体设置建议: 对于数据量较小的配置表, 设置全表缓存, 对于数据量较大的常用表, 比如MARA表,设置单记录缓存)
通过当前程序中的变量缓存表,性能最好,但是针对复杂调用层级的程序实现比较麻烦. 酌情使用.
自定静态类的表缓存 性能与实例类,函数缓存性能差不多. 推荐使用该方式. 复杂程序可以很方便的使用. 缓存性能比表的技术设置缓存性能高出3倍(全表缓存) , 2倍(单记录缓存)
十一
总结
通过缓存读取表可以优化整个程序的性能.
大部分程序可以通过表的技术设置或CDS视图的缓存方式优化性能.这种优化不改变程序逻辑,实现简单方便.但是性能不如程序中的主动缓存.
程序中的全局内表缓存性能最好, 但不具备通用性.
函数/静态类缓存逻辑清晰,通用性好,性能稍差于程序中的全局内表,但适用性好. 推荐在项目中使用.
标准函数MARA_SINGLE_READ就是此类应用的示例.
另外标准缓存功能(技术设置或CDS视图的缓存)是持续生效的,除非因为总的缓存空间不足而被清理. 但是也会导致多程序间互相竞争缓存资源,导致特定程序重复缓存.
而程序中的缓存仅对当前会话执行有效.
缓存会占用更多的内存空间,属于用空间换取时间的做法. 对于占用大量空间的程序导致内存溢出的, 则需要及时清除并减少缓存数据.
THE
END
约定
如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.
请微信联系管理员:
syjf1976
sharry_xlp
Yannick_Duan
申请进入公众号讨论群提问或者参与话题讨论