Progress-4GL 创建缓冲区时能否限定其数据搜索范围
关于缓冲区自定义限定范围的实现说明
DEFINE BUFFER 原生语法本身不支持在定义行直接追加WHERE子句来绑定固定数据范围。缓冲区本质是对应表/临时表的内存操作句柄,本身没有持久化存储过滤规则的属性,你尝试编写的DEFINE BUFFER ex1 FOR emit WHERE emit.id > 50000 属于不被支持的非法语法。
如果你的业务需求是让某个缓冲区永久绑定固定的查询范围、不需要每次遍历重复写WHERE条件,可以通过给缓冲区关联固定配置的QUERY对象实现等效效果,示例代码:
/* 定义目标缓冲区 */ DEFINE BUFFER ex1 FOR emit. /* 给缓冲区绑定固定查询,把过滤条件固化在查询配置里 */ DEFINE QUERY q-ex1 FOR ex1 SCROLLING. OPEN QUERY q-ex1 FOR PRESELECT ex1 WHERE ex1.id > 50000. /* 后续遍历直接走这个固化的查询,不需要重复写WHERE条件 */ GET FIRST q-ex1. DO WHILE NOT QUERY-OFF-END("q-ex1"): DISPLAY ex1.id ex1.name. GET NEXT q-ex1. END.
只要你不主动修改这个QUERY的过滤条件,该缓冲区的所有遍历结果都会被限定在你最初定义的范围内,完全可以实现“缓冲区自带数据范围限制”的效果,适配你的业务诉求。
现有业务代码的效率优化方案
你当前代码的性能瓶颈主要来自三点:无索引的临时表嵌套比对、冗余的临时表中转、可能的全表无索引扫描。对应的优化都是ABL开发里的常规性能优化思路:
- 删除完全冗余的临时表中转
你当前代码里的tt-oper属于多出来的中间层,仅把tt-min-oper里op-codigo <>10的物料复制了一遍,这一步会额外增加一次临时表全遍历、写入的开销,完全可以删掉。
同时给所有临时表加上匹配字段的索引,避免嵌套遍历的时候做无索引的逐行比对:
删掉原来遍历def temp-table tt-min-oper field it-codigo like operacao.it-codigo field num-id-operacao like operacao.num-id-operacao field op-codigo like operacao.op-codigo /* 给后续关联的匹配字段加索引,大幅提升关联速度 */ index idx-it it-codigo . def temp-table tt-valida-oper field it-codigo like operacao.it-codigo /* 加唯一索引,避免重复写入同个物料的重复记录 */ index idx-it it-codigo unique .tt-min-oper写入tt-oper的整段逻辑,把原本对tt-oper的过滤条件直接挪到后面的关联查询里:FOR EACH operacao NO-LOCK, EACH tt-min-oper NO-LOCK WHERE operacao.it-codigo = tt-min-oper.it-codigo AND tt-min-oper.op-codigo <> 10 AND operacao.op-codigo = 10: CREATE tt-valida-oper. ASSIGN tt-valida-oper.it-codigo = operacao.it-codigo. END. - 优化首条记录的提取逻辑
你当前提取每个物料第一条操作记录的逻辑,是全表扫描operacao再加BREAK BY排序,如果operacao表没有(it-codigo, num-id-operacao)的复合索引,这一步会触发全表扫描+磁盘临时排序,开销极大。
只要表上存在it-codigo升序的索引,这一步不需要做任何逻辑调整,就能只读取每个物料的第一条匹配记录就结束,不需要全表遍历所有行。 - 百万级大表场景的无临时表优化
如果operacao表的数据量超过百万级,连tt-min-oper临时表的读写开销都可以省掉。你当前的业务逻辑本质是筛选“存在非10类型初始操作、同时存在10类型操作记录”的物料,完全可以通过自关联operacao表实现,不需要任何临时表中转:
这种写法全程会走表上的现成索引,不会触发全表扫,性能会比多临时表中转的方式高一个数量级。/* 优先走op-codigo的索引,直接定位所有op-codigo=10的操作记录,减少扫描量 */ FOR EACH operacao NO-LOCK WHERE operacao.op-codigo = 10, /* 利用it-codigo的索引,关联找同个物料下存在非10类型的操作记录 */ EACH operacao ex-init NO-LOCK WHERE ex-init.it-codigo = operacao.it-codigo AND ex-init.op-codigo <> 10: CREATE tt-valida-oper. ASSIGN tt-valida-oper.it-codigo = operacao.it-codigo. END.
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

