sql優化:數據量過大查詢優化


1.場景:有大數據的數據需要放到首頁統計,一般就是聚合、分組之類的,按照年月日進行查詢和統計。如果數據量比較少,幾十萬數據 沒什么問題。但是隨着數據量的增多,查詢速度越來越慢。這個時候就需要去優化了~

   剛開始自己的想法是這樣的:使用多線程的方式,因為查詢每天的數據量很少,那么是不是可以使用多線程的方式,每個線程查詢一天的,查詢一個月30天,就用30個線程,這樣速度會不會快些?

於是,用多線程的方式實現了下。代碼如下:

 

    private ExecutorService executorService = new ThreadPoolExecutor(30,30,1, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>());
    public List<Map> getCiServiceBadEvaNumStatistic(SAASIndexQuery saasIndexQuery) throws InvocationTargetException, IllegalAccessException {
        String startDate = saasIndexQuery.getStartDate();
        String endDate = saasIndexQuery.getEndDate();
        int days = DateUtil.getDatebetweenOfDayNum(DateUtil.parseDate(startDate,DateUtil.dateFormatPattern),DateUtil.parseDate(endDate,DateUtil.dateFormatPattern));

        CompletionService<List<CiOrderStatisticSection>> completionService = new ExecutorCompletionService<List<CiOrderStatisticSection>>(executorService);

        List<CiOrderStatisticSection> allList = new ArrayList<>();

        long start = System.currentTimeMillis();
        logger.info("測試異步時間start:" + System.currentTimeMillis());
        //CountDownLatch countDownLatch = new CountDownLatch(days);
        SAASIndexQuery everyDaySaas = new SAASIndexQuery();
        BeanUtils.copyProperties(everyDaySaas,saasIndexQuery);
        for(int i = 0;i<days;i++){
            everyDaySaas.setStartDate(DateUtil.afterNDay(saasIndexQuery.getStartDate(),i,DateUtil.dateFormatPattern));
            everyDaySaas.setEndDate(DateUtil.afterNDay(everyDaySaas.getStartDate(),1,DateUtil.dateFormatPattern));
            //countDownLatch.countDown();
            int finalI = i;
            completionService.submit(new Callable<List<CiOrderStatisticSection>>() {
                @Override
                public List<CiOrderStatisticSection> call() throws Exception {
                    //allList.addAll(biSaasCiDeviceDayExMapper.getCiServiceNegativeRate(saasIndexQuery));
                    //countDownLatch.countDown();
                    System.out.println("====="+ finalI +"=====");
                    return biSaasCiDeviceDayExMapper.getCiServiceNegativeRate(saasIndexQuery);
                }
            });
        }
        System.out.println("==============" + (System.currentTimeMillis()-start) + "毫秒");
        long t = System.currentTimeMillis();
        for (int i = 0;i<days;i++){
            System.out.println("for循環耗時==============+"+i + (System.currentTimeMillis()-t) + "毫秒");

            try {
                Future<List<CiOrderStatisticSection>> future = completionService.take();
                List<CiOrderStatisticSection>  ciList = future.get();
                allList.addAll(ciList);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        logger.info("測試異步時間end:" + (end-start) + "毫秒");
        System.out.println("測試異步時間end:" + (end-start) + "毫秒");

}

測試后發現不對,使用多線程的take方式 每次都會有阻塞,這個阻塞一直沒明白是哪里阻塞了? 是線程池、LinkedBlockingDeque 還是for循環 take時候 阻塞了 一直沒明白,觀察的結果就是每次for循環都要差不多200多毫秒,30個循環要6s多。。。。額,算了 ,還沒有原來快呢

 

 

2.昨天換了種思路:直接從數據庫查詢時候做好控制。每次查詢先根據月份和年份,查詢出來id的最大值和最小值,之后sql里面查詢時候加上id在這個最大值和最小是區間內。大概思路是這樣:嗯,結果竟然可以。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM