最近接到一个需求,用户表示有个查询供应商发票的报表跑不出来,要么很慢要么dump,希望调整一下。分析了一下原因,发现是有一个不久前增加的查询条件,付款日期,导致的。这个日期是发票日期+账期计算出来的,不能直接作为过滤条件,导致必须先查询出海量的冗余数据,然后再计算,再过滤,难免很慢。用户又非常喜欢这个查询条件。其实多增加几个查询条件是可以提高效率的,但我们都知道,改变用户的使用习惯难如登天,所以尽量解决问题,实在不行再
解决 改变用户。
一个处理思路就是用CDS把计算逻辑前置,这样ABAP在查询的时候可以直接过滤数据。
CDS代码如下。
@AbapCatalog.sqlViewName: 'ZCDS_V_PAYDATE'@AbapCatalog.compiler.compareFilter: true@AbapCatalog.preserveKey: true@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'calculate pay date'define view zcds_e_paydate as select from rbkp inner join rseg on rbkp.belnr = rseg.belnr and rbkp.gjahr = rseg.gjahr left outer join mkpf on rseg.lfbnr = mkpf.mblnr and rseg.lfgja = mkpf.mjahr { key rbkp.gjahr, key rbkp.belnr, key rseg.buzei, rbkp.bktxt, rbkp.bldat, rbkp.lifnr, ...... ...... rseg.wrbtr, mkpf.budat as budat_gr, CONCAT(rbkp.belnr,rbkp.gjahr) as awkey, DATS_ADD_DAYS(rbkp.bldat,cast(cast(cast(zbd1t as ABAP.CHAR(5)) as ABAP.NUMC(5)) as ABAP.INT4),'INITIAL' ) as paydate }
在ABAP里把查询rbkp和rseg表,调整为查询此CDS,付款日期直接对应paydate字段。对比一下结果。查询付款日期在2022年12月上旬的发票。调整前,运行时间超过设定的1800秒,被系统强制dump了。调整后,37秒出结果。
concat和dats_add_days是CDS的内置函数。budat_gr字段、awkey字段,也是为了解决类似的问题增加的。
多说几句。CDS的效率并不高,我自己做过测试。它和你写的Open SQL语句相比,从查询效率上没有优势,甚至比Open
SQL还慢。或者应该这么说,CDS不是用来简单粗暴提高数据库应用体验的。可以用古老的逻辑数据库类比。逻辑数据库的优势不是数据库,而是逻辑。区别就是,CDS的逻辑需要我们自己写。
SAP推CDS,应该有一部分考虑是让SAP和ABAP解绑。不是废掉ABAP,而是多一条路,让ABAP不再是唯一。对于传统的ABAP来讲,其实不懂CDS,也没什么影响。但正因为不用了解,所以才需要了解。艺多不压身,多一门手艺多一块收入。