记一次Oracle千万级数据查询与千万级数据新增的调优过程

因为业务需要,我要做一个后台接口,用来处理一个月的生成订单的处理。查询的数据量维持在九百万条数据左右。

我第一次是在dev环境跑的单元测试,没有考虑到这么大的数据量,sit造的数据量也不大,等到hotfix就懵逼了,一下查出了900多万条,仅仅是查询就耗费了很长时间,查询之后还要进行insert,每次insert还要验证数据是否重复。结果就是直接把做系统整瘫痪了。

记一次Oracle千万级数据查询与千万级数据新增的调优过程_第1张图片

这段sql不忍直视,而且更严重的是,我把查询出来的结果都放到了list里面,这就把JVM所有的内存都沾满了,其他人的定时任务就没法跑了。

优化:

1、SQL拆分优化:

开始的时候我用的是UNION ALL ,但是嘛,下面那个select函数查询的数据量其实很小,所以可以将两个sql分开。这样可以节省一部分时间。

2、将not in改为not exists

and not exists( select 1 from FEE_ORG_*** c where c.MY_ORDER_ID = a.my_order_id and start_date = to_number(@startDate) and end_date = to_number(@endDate))(后面这个将去掉,因为在存储的时候还要做一次校验,这个not exists会拖慢整体速度。)

3、and  to_char(a.LATEST_STATUS_TIME,'yyyyMMdd') >= to_char(SYSDATE + ( 1 - @day)),将左边的to_char去掉,转换右边的就可以了,因为左边的字段to_char会将查询结果的每一条数据都进行转换,而转换右边的只需要转换一次就可以了。

4、去掉所有的to_number,只需要再传入参数的时候进行初始化为int型就可以了。

5、加索引,create index fee_order_**_01 on fee_order_**(start_date ,end_date,MY_ORDER_ID);

6、在distinct之前加一个/*+ leading(a) index(a idx_efsw_loan_**_01) */,因为业务需要这几个关联的表必须进行join关联,速度不可避免的会很慢。加了/*+ leading(a) index(a idx_efsw_loan***_01) */主要是为了强制是efsw_loan***表作为主表进行关联查询。经过以上优化,百万级查询只需要十几秒;

7、sql优化之后,接下来就是程序的优化了,优化的思想就是分页查询,不能一次性的将所有的数据查出来放到list中, 我采用的是每次查5000,执行5000条,下面是代码优化:

记一次Oracle千万级数据查询与千万级数据新增的调优过程_第2张图片

最后在dev环境进行了实验,数据是20万,每次执行的条数是5000条,耗时30秒 

记一次Oracle千万级数据查询与千万级数据新增的调优过程_第3张图片

你可能感兴趣的:(Oracle,java,web项目)