【实战】大批量数据导出的计划
布景
业务需求导出将近6w多的全单位的数据,有些数据在其时表中不存在,需求现计算。这个功用是汇总的功用,并且涉及的表很多(将近40张),表是真TM的多,需求显现的字段也是超多,我是真服了,其时是怎么规划的。
计划
优化架构和表结构是不可的,只能在这40张表的基础上持续搞。想的办法是分隔批量查询。主体思维便是先把首要的数据查询出来,再写多个子查询(涉及到计算的),子查询都用 in 来写,一次查询上千条,然后这样再分批次,最终再汇总。
详细实现操作
这是主表,首要的数据,里面会查询出project_id,再去根据project_id 去作为其他子查询的条件。这儿 * 省掉详细的字段。
select * from
serp_em_project_info a
left join serp_em_construction_plan b
on a.project_id = b.project_id
left join serp_em_project_account_info c
on a.project_id = c.project_id
left join js_sys_office o
on a.office_code = o.office_code
left join serp_base_project_developer d
on a.project_developer =d.project_developer_id
left join js_sys_area e
on a.construction_area = e.area_code
left join js_sys_office uo
on uo.office_code = a.undertaking_office
left join js_sys_user creator
on creator.user_code =a.project_manager
然后再分批次,sumAmountHandlerList 办法中传的参数便是 咱们查询出的首要数据
public List<Map<String, Object>> sumAmountHandlerList(List<Map<String, Object>> list) {
// 一批次的数量,将2500 个 project_id 放在一个调集里
int batchNumber = 2500;
// 循环
int iteratorCount = (int) Math.ceil((double) list.size() / batchNumber);
for (int i = 0; i < iteratorCount; i++) {
int startIndex = i * batchNumber;
int endIndex = (i < iteratorCount - 2) ? (startIndex + batchNumber - 1) : (list.size() - 1);
// 取一切的 'projectID'
List<String> projectIds = new ArrayList<>();
for (int j = startIndex; j <= endIndex; j++) {
projectIds.add((String) list.get(j).get("project_id"));
}
//核定告贷合计,核定告贷金额,子查询,需求现计算
List<Map<String, Object>> individualBorrowList = projectReportDao.individualBorrowCollection(projectIds) ;
// 数据处理
for (int j = startIndex; j <= endIndex; j++) {
Map<String, Object> item = list.get(j);
// 核定告贷金额(authorized)
item.put("authorized", 0D);
for (Map<String, Object> authorizedItem : individualBorrowList) {
if (((String) authorizedItem.get("project_id")).equals((String) item.get("project_id"))) {
item.put("authorized", Double.parseDouble(authorizedItem.get("authorized").toString()));
break;
}
}
}
这块,首要讲一下,怎么分批次。先获取到主体数据的总数,再根据一个批次里的数量,获取到需求几个批次,就能够悉数加载完数据。也便是外循环几回。
// 循环
int iteratorCount = (int) Math.ceil((double) list.size() / batchNumber);
for (int i = 0; i < iteratorCount; i++) {
int startIndex = i * batchNumber;
int endIndex = (i < iteratorCount - 2) ? (startIndex + batchNumber - 1) : (list.size() - 1);
第一次内循环是从0开端,第2次内循环便是 1 * 批次数量,依次类推。 int startIndex = i * batchNumber;
第一次内循环是从(批次数量-1) 完毕,因为是从0开端的,第2次内循环便是 2500开端,到2500+batchNumber – 1 完毕,
最终一次内循环便是 总数-1;
这儿比较绕,梳理通了,整体就简略了,最好是带上详细的数字就简略多了。
然后便是在内循环中,根据project_id ,进行比对,相同的,将数据组合在一起。
其他计划
其时,也有考虑采取守时使命,在凌晨将数据悉数算好,然后放到一张表里,这样直接查询一张表,必定功能会更好一些。但数据会存在推迟性,当天审批过的数据,业务人员无法查看到,只要第二天守时使命完了,才能够查询。采取分批次子查询的计划查询在1s内就能够查询出来,导出时,由于数据较多,需求五六分钟(将近20M),业务人员也能够承受。
看看,大家还有什么比较好的计划?欢迎讨论。