本文介绍了苍穹平台在性能优化方面的多个策略,包括列表查询优化(如IdQuery与SqlQuery对比、模糊查询方式选择、列表数据限制和默认排序关闭)、查询数据方式的最佳实践(使用帮助类、流式取数、缓存数据等)、水平分表以提升大数据量下的查询性能、读写分离以减轻数据库压力、以及in查询优化解决参数过多问题。每种优化策略均详细阐述了背景、用法及注意事项,并提供了参考链接和配置路径。
1 前言
在上篇文章中我们了解了在苍穹定制化开发系统,查询慢的原因以及一些常见慢sql 的案例,大部分是通过调优sql 的方式,索引方面的内容。那么除了调优sql,结合实际的业务场景,苍穹平台也提供了一些性能方面的优化,我们在实际业务开发过程中是可以直接调用或者通过配置实现的。这个篇幅我们从列表查询,如何查询数据,水平分表,读写分离以及in 查询优化等几个方面来讲解下这些优化点以及介绍它们的用法。
2 列表查询优化
2.1 查询方式
1.背景:列表查询目前默认使用的是IdQuery 查询方式,该方式会产生两个SQL,第一个SQL 是将一些关键字段,合计字段以及排序字段作为查询字段,然后取TOP10W 数据进行查询,由于这些字段没有建索引导致扫描数据较多,当数据量很大时会出现第一次加载很慢的情况,性能较差。目前平台提供了sqlQuery 的优化方式,此方式采用数据库的分页方式查询,直接返回一页数据。
更详细内容请参考:https://vip.kingdee.com/article/160397783294264832
2.用法:选择查询方式为sqlQuery 查询模式,平台已经提供可配置方式
如下图所示:
3.如果有自定义取数的情况下,比如列表加载第三方数据(非数据库数据源)等,使用SqlQuery 模式下需要对getRealCount,getBillDataCount,getSummaryResults 三个方法进行重写。因为在IdQuery 下都是取数一次返回
的,在getData 方法通过getQueryResult().setDataCount(dataCount);getQueryResult().setBillDataCount(billDataCount);
getQueryResult().setSummaryResults(summaryResults);进行设置数据,而在SqlQuery 模式下列表取条数,张数,以及合计数都是异步的,SqlQuery 模式下无法生效。
注:如果是直接使用的getQueryBuilder().getFilters()查询,这种情况下不需要重写getRealCount,getBillDataCount,getSummaryResults 三个方法。
2.2 模糊查询
1.背景:目前列表快速搜索默认采用全字匹配的方式,如果数据量较大的情况下,sql 的索引会失效,性能较差。目前平台提供了可配置的方式,用户可自行选择是通过包含或是以...开始的方式进行查询。
注:
(1)包含:使用%*%的方式进行数据库查询,将字段包含关键字的数据查询出来,对查询性能消耗较大;
(2)以...开始:使用左包含的方式进行数据库查询,将字段前缀与关键词匹配的数据查询出来,对查询性能消耗较小。
2.用法:在单据参数中将模糊查询方式改为“以.....开始”
注:生效范围(对系统PC 端、移动端的模糊查询生效,包括快速搜索视图、搜索控件、基础资料F7 模糊查询)
2.3 列表数据限制
1.背景:目前列表的默认查询是10W 条数据,数据量较大,加载的时间较长。
2.用法:在业务允许的范围内,可以将单据参数中的“列表查询最大限制数”调小一些。
2.4 默认排序
1. 背景:默认排序开启时,效果如同2.1 所说IdQuery 的查询方式,会产生两条sql,在大数据量的情况下,性能较差。
2. 用法:在列表中将默认排序关闭(后续7 月大版本会上线)
3 查询数据方式
1. 目前在苍穹平台获取数据的方式有查询服务帮助类QueryServiceHelper,业务数据服务帮助类BusinessDataServiceHelper,还有根据实体模型访问ORM以及使用DB 通过路由key 访问数据表的方式,那么这些方式应该怎么使用,才能够最大程度的发挥性能优势?
(1)在使用帮助类时,除了根据查询的数据是否需要保存的角度去选择,还可以结合业务场景,如果可以使用缓存的数据,那么可以使用BusinessDataServiceHelper.loadSingleFromCache 的方式,此方法会优先从缓存中取。
(2)对于大数据量的查询,如果不需要对数据做保存等操作,可以考虑使用QueryServiceHelper.queryDataSet 的方式,该方法是流式取数,性能较快。同样的,使用ORM.create().queryDataSet()或DB.queryDataSet()也是一样的原理。
这几个方法返回的是DataSet,DataSet 是结果集转换器,也是迭代计算,通过
ORM.create().toPlainDynamicObjectCollection()可以转换为结果集。此方式其实就是苍穹分布式引擎计算Algo 的体现。
注:使用查询时应避免查询所有的字段或是在循环中做查询操作。
2.Algo 通过宿主机内存计算代替数据库计算,减轻数据库压力,解决数据库性能瓶颈,适用于大数据量且需要进行多次计算的场景,且是作为报表的开发框架。
Algo 详细内容请参考:
https://dev.kingdee.com/index/docsNew/7a22b9ce-805f-4805-b78c-cce57ce2ad8e
4 水平分表
1. 背景:当数据超过一定量级后,无论是对于数据查询还是数据更新,在经过索引优化等纯数据库层面的传统优化手段之后,还是可能存在性能问题。在这种场景下,就需要考虑使用分表了。即把数据按照一定的规则拆分成多张表,来解
决单表环境下无法解决的存取性能问题。目前比较主流的是开源中间件是Sharding-jdbc 和Mycat。在苍穹平台中,是支持水平分表的,并且通过简单的配置即可实现。
2. 用法:
(1)配置水平分片之前须启用XDB,否则分片配置不生效,数据迁移服务也不会执行。
在配置管理中设置xdb.enable=true,若是本地开发环境,可以自定义:
System.setProperty("xdb.enable", "true")。通常只需要配置xdb.enable。
XDB 的配置,均通过系统环境属性设置:
(2)入口:系统云—>配置工具—>水平分表—>分片表单配置
(3)新增分片
(4)选择对应的分片属性,分片策略,启用分片并完成数据迁移
参考链接:
https://dev.kingdee.com/index/study/detail/9357a2a3-70d2-4a27-8826-0951
ff492f96?from=allCourse
5 读写分离
1. 背景:如果在实际项目中,场景是读远多于写的,并且目前读的性能较差,那么可以考虑使用读写分离。数据库的“写”相较于“读”更加耗时,因此写入操作会影响查询的效率,采用读写分离能分摊数据库的压力,提高性能。苍穹平台已经提供了入口,如需实现读写分离,通过配置的方式即可实现。
2. 用法:
(1)入口:租户管理中心—>租户列表—>点击进入租户界面
(2)启用读写分离
(3)新增只读库
注:苍穹系统已使用读写分离的功能:列表、F7、报表
参考链接:https://vip.kingdee.com/school/94533581439334144
6 in 查询优化
1. 背景:为了解决in 查询参数过多导致的数据库参数限制问题和查询性能问题,
苍穹产品提供临时表和in 查询拆分两种优化解决方案。
2. 用法:在管理中心中配置以下参数:
3. 是否开启IN 查询优化:orm.opt.in.enable=true;
4. IN 查询优化方案(temp,split):orm.opt.in.type=temp
5. 开启IN 优化阀值(IN 查询参数个数>=优化阀值时,启用IN 查询优化):
orm.opt.in.threshold=1000
6. IN 查询允许的最大个数:orm.opt.in.maxsize=500000
参考链接:https://vip.kingdee.com/article/81049088208139776
下载路径:云之家企业云盘
企业文件->【苍穹平台】共享资料库05->定制化开发标准化工具包->03开发规范
如有疑问或者更好的建议,欢迎小伙伴留言或者私聊~
苍穹定制化开发性能优化专题系列(二).pdf(564.15KB)
推荐阅读