查询时数据量大的解决方案

情景:

前几天在工作上遇到个优化需求,某个接口速度几乎接近了10s,这会严重影响用户操作感受,在开发上也是无法接受的,于是我开始着手进行了接口优化。

第一步:SQL优化

首先查看代码里面的逻辑优化,感觉问题不大,于是进一步查看具体的Sql,对sql进行优化,这里可以参考我前面写的sql优化场景。在进行了适当的冗余以及增加索引后,此时的Sql已经差不多接近6s,虽然有所进步,但还是远远不够,但详细看代码逻辑部分已经没有可以优化的部分了,此时就可以使用多线程了。

第二步:多线程查询

这个的大体思路是这样的,用一个线程进行查询慢,那我就使用多线程,每个线程处理一部分的数据,最后聚合起来返回,这样查询速率就可以显著提升。核心多线程代码如下:

 List<List<Long>> subLists = new ArrayList<>();
        // 数据大小
        List<Long> ids = buSignatureMapper.selectSignatureCount(ro);
        // 批次大小(每个线程要处理数据量)
        int batchSize = 20000; // 每个子列表的大小为2万
        // 分割List为多个子列表
        for (int i = 0; i < ids.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, ids.size());
            List<Long> subList = ids.subList(i, endIndex);
            subLists.add(subList);
        }
        Queue<CureListVo> results = new ConcurrentLinkedQueue<>();
        if (ObjectUtil.isNotEmpty(subLists)) {
            // 使用定长线程池,大小根据实际情况调整,例如数据库连接数、CPU核心数等
            int poolSize = Math.min(subLists.size(), Runtime.getRuntime().availableProcessors());
            ExecutorService executor = Executors.newFixedThreadPool(poolSize);
            CountDownLatch latch = new CountDownLatch(subLists.size());
            for (List<Long> subList : subLists) {
//                System.out.println(subList.get(0));
//                System.out.println(subList.get(subList.size()-1));
                CureListRo ro1 = new CureListRo();
                BeanUtil.copyProperties(ro,ro1);
                ro1.setStartIndex(subList.get(0));
                ro1.setEndIndex(subList.get(subList.size()-1));
                executor.submit(() -> {
                    try {
                        // 查询MySQL表操作
                        List<CureListVo> cureListVos1 = buSignatureMapper
                                .selectCureList(ro1);
                        // 直接添加到ConcurrentLinkedQueue中,它是线程安全的
                        System.out.println(ro1.getStartIndex()+"到"+ro1.getEndIndex()+"total"+cureListVos1.size());
                        results.addAll(cureListVos1);
                    } finally {
                        // 计数器减一,表示一个任务完成
                        latch.countDown();
                    }
                });
            }
            // 阻塞等待所有查询任务完成
            try {
                latch.await();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("Thread pool interrupted while awaiting termination: {}", e.getMessage());
            } finally {
                // 关闭线程池
                executor.shutdown();
            }
        }
        List<CureListVo> cureListVos = results.stream().sorted(Comparator.comparing(CureListVo::getCureEndTime).reversed()).collect(Collectors.toList());

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值