# 查询性能问题解决方案
# 方案之索引
1、对于ctp_affair表,参考高版本的索引创建,并确保所分析sql正确使用该索引。
2、没有固定方案,分析sql,合理建立索引。
# 方案之分步查询
# 原理
去除连表查询,使用单表查询策略,将多次单表查询的结果合并后返回。
# 适用场景
查询sql是多表关联,查询结果集需要展示多表字段内容,默认查询条件全部在一个表中,其他查询条件全部或者部分都在同一个表中。
# 改造方案
1、梳理sql,整理查询条件各字段属于哪个表关系清单,整理各展示字段属于哪个表关系清单。
2、将查询条件所在的表执行一次查询,将此表需要的字段先查出来,同时达到分页效果。
3、根据第2步结果,使用关联字段再去其他表中单独查询数据,最后将数据与第一次查询的结果集合并到一起后返回。由于已经分页,所以查询其他表的数据量相当少,耗时忽略不计。
4、判断接口传入的条件,如分步在多个表,依旧执行多表关联查询。
# 优缺点
优点:
改造成本低、仅需处理dao层sql拼接逻辑。
影响范围小,基于dao层处理,外部使用不受影响,对业务造成的影响小。
缺点:
- 并非所有场景都适用,需要分析sql是否符合分步要求。
- 不一定所有条件都支持分步要求,可能存在部分查询条件依旧需要走连表。
# 案例
某所ctp_affair表1.25亿数据,其中协同数据1.16亿,公文0.09亿,体现在协同待办、协同已办、公文待办、公文已办耗时较长。分析查询语句发现,使用ctp_affair表与col_summary或者edoc_summary表关联,大部分查询条件都在ctp_affair表,极少部分在summary表中。使用多账号多场景验证sql,连表查询平均耗时0.30秒,单表查询平均耗时0.03秒(oracle数据库,缓存无法完全清除,无法准确定位首次请求,体现不出几十秒的效果。数据均在存在缓存的情况下多次查询得出),速度提升10倍。改造后监控capability.log请求日志,客户早高峰使用期间,接口平均耗时由5秒降低至1秒。
# 方案之分库
# 原理
数据库均有一个阈值,此阈值根据数据库硬件条件、参数设置等变化。一旦数据量超过此阈值,查询效率将急剧下降。通过分库,将数据拆分到其他数据库,以减少数据角度提升查询性能。
# 适用场景
已经采用其他方式提升查询性能,随着数据增长,的确由于数据太多导致性能无法再提升。迁移的数据仅做查询使用,不继续处理。
# 改造方案(以协同转储分库为例)
1、创建分库
2、将已完结,且发起时间为两年前的协同数据迁移至分库,协同数据包含col_summary、ctp_affair及其他相关联的各表(根据表在业务中使用情况可以有所变化)
3、前台页面新增入口用于查询分库数据,查询条件根据实际情况做增减,如查询使用多表关联,需确保都在同一个数据库。否则可以考虑减少查询条件,或者增加表一起迁移至分库。
4、配置分库数据源,通过配置不同的bean,控制查询主库或是分库。
注:标准产品v6.1sp2及以上版本支持协同业务转储,插件控制
# 优缺点
优点:
- 最后解决方案,从数据量角度,根本上解决问题。
缺点:
- 改造成本大,预估不少于20人/天,业务代码几乎需要全场景适配,v6.1sp2版本以下额外涉及平台底层改造支撑。
- 影响范围大,与业务展现相关所有场景均可能造成影响,如改造不完善,将导致部分功能无法正常展现数据。
# 案例
某局ctp_affair表8千万+采用分库策略,迁移4千万数据到分库后,在其他条件不变的情况下,查询速度由1分+降至20秒+
