# 查询性能问题解决方案

# 方案之索引

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秒+

编撰人:lichaoj、admin