列表合计和排序优化
背景
有业务反馈列表开启了合计和排序功能时,在 IdQuery模式下会产生两个SQL,第一个SQL是将一些关键字段,合计字段以及排序字段作为查询字段,然后取TOP 10W数据进行查询,由于这些字段没有建索引导致扫描数据较多,性能较差。IdQuery查询模式的原理是先查出10W个ID,然后将10W个ID放在Redis,下次翻页时,可以直接根据缓存的10W个ID来获取当页ID并拼在Sql后面来加速当页数据的获取,之所以可以加速是因为翻页时从redis取到id的速度很快,同时Sql查询时可以使用id走索引来加快Sql查询。但是这种查询模式的问题在于之前取10W的ID时由于附带了合计,排序还有条数统计的功能,所以当数据量很大时会出现第一次加载很慢的情况。
优化方式
列表设计器增加开关“默认排序”复选框
“默认排序”关闭的时候(跟SqlQuery一样)
1.直接返回一页数据
2.第二次请求过来取条数,页数
3.通过“合计”复选框来取汇总数据
“默认排序”打开的时候
1.取10W个id,带排序字段
2.返回一页数据给前端,不处理合计数据,小于10W条直接返回条数
3.大于10W条的情况下,前端再过来取条数
4.通过“合计”复选框来取汇总数据
上面和目前IdQuery之前处理的区别在于
第2条,小于10W条的情况下目前IdQuery会取合计数据
第4条,大于10W条的情况下才通过“合计”复选框来取汇总数据
如果数据量比较大的情况下可以尝试将“默认排序”开关关闭,此模式基本和SqlQuery模式一样,但是有些地方需要注意。
SqlQuery模式需要改造点
目前列表使用的IdQuery查询模式,这种模式会先取10W个ID,然后再根据分页条数进行二次取数;如果有排序字段和汇总字段的情况,第一个取数sql还会带上排序字段和汇总字段进行查询,如果数据量比较大的情况下,第一个sql可能会产生性能瓶颈。还有一种查询方式是SqlQuery,SqlQuery的查询方式采用数据库的分页方式查询,只有一个sql,而且是取当页数据,列表的条数是串行取的,这种查询方式性能相对较好,平台目前想把查询方式默认改为SqlQuery;
但是如果有自定义取数的情况下,比如如下场景:
1. 用列表加载第三方数据,非数据库数据源
2. 在自定义取数逻辑,对数据集合进行加工,增加或减少数据
3. 在自定义取数逻辑,增加了额外的过滤条件
等。。。
因为,SqlQuery模式下,列表取条数,张数,以及合计数都是异步,或者需要用户点击进行取数,之前这些数据在IdQuery 下都是取数一次返回的,在getData 方法通过
getQueryResult().setDataCount(dataCount);
getQueryResult().setBillDataCount(billDataCount);
getQueryResult().setSummaryResults(summaryResults);
进行设置,但是SqlQuery模式下无法生效所以在SqlQuery模式下我们提供了三个方法进行重写,getRealCount,getBillDataCount,getSummaryResults,如果有以上或者类似场景需要业务进行重写
注意
这里如果取数时不是直接使用的getQueryBuilder().getFilters()查询,比如直接调用super处理,没有自己处理,这种情况下不需要重写getRealCount, getBillDataCount, getSummaryResults
示例:beforeCreateListDataProvider(自定义取数)
@Override public void beforeCreateListDataProvider(BeforeCreateListDataProviderArgs args) { System.err.println("beforeCreateListDataProvider"); args.setListDataProvider(new ListDataProvider(){ @Override public int getRealCount() { // 获取真实条数 } @Override public int getBillDataCount() { // 获取单据张数,只统计单据头的数量 } @Override public List<SummaryResult> getSummaryResults() { // 获取合计字段值 } @Override public DynamicObjectCollection getData(int start, int end) { int dataCount=selfQueryDataCount(); int billDataCount=selfQueryBillDataCount(); List<SummaryResult> summaryResults=selfQuerySummaryResult(); // 自己的取数逻辑得到DynamicObjectCollection, // 这里如果取数时不是直接使用的getQueryBuilder().getFilters()查询,比如直接调用super处理,没有自己处理,这种情况下不需要重写getRealCount, getBillDataCount, getSummaryResults DynamicObjectCollection dynamicObjectCollection = selfQueryData(); getQueryResult().setCollection(dynamicObjectCollection); getQueryResult().setDataCount(dataCount); getQueryResult().setBillDataCount(billDataCount); getQueryResult().setSummaryResults(summaryResults); return dynamicObjectCollection; } }); super.beforeCreateListDataProvider(args); }
列表合计和排序优化
本文2024-09-23 00:22:48发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-139091.html