记录一次工作中的SQL优化,临时表和CountDownLatch

背景:CRM管理系统,大量的权限配置,包括读写等权限,每个人都可能不同,也就是说每个人都有自己的权限体系。设计初期要使用用户的gid来确定用户的具体权限。

优化前:该代码逻辑为同事所写。因为用gid来确定用户的权限,在做某个操作的时候就不可避免的用到in,开发测试环境数据量少,速度不明显,上了生产,选择某部门,某年的数据时,反馈的gid可想而知。刚巧这的功能为统计,要统计4种不同的业务数据,导致统计功能反馈时间10多秒啊,这自然是不能容忍的。

开始优化:

第一步,查看sql,确定sql执行速度。没啥毛病,慢的狠。MySql数据库in后面长度不限,真是要多长有多长。于是开始对sql进行优化。基础优化,DISTINCT关键字改成group by。in后面的海量数据,改为建立临时表。在优化的时候,遇到取交集的情况,用了UNION ALL, GROUP BY gid HAVING COUNT(gid) > 1的方式来取两张临时表的交集。至此,新建临时表优化效率结束,查看查询效率,有了很大提高,但还是偏慢。

第二步,使用多线程。因为业务场景是统计4个数据,每个数据都有独立的查询统计方式,所以这里使用多线程,来查询4个统计。并得到反馈。效率得到了显著提升。多线程使用CountDownLatch,代码如下,只粘贴多线程相关,并没有粘贴业务方面代码:

private final static int threadCount = 4;

private final static ExecutorService exec = Executors.newCachedThreadPool();
 
final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            int finalUserGidsFlag = userGidsFlag;
            exec.execute(() -> {
                try {
                    execCountThread();
                } catch (Exception e) {
                    logger.error("统计销售简报错误",e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();

优化后:优化后,查询效率得到了明显提升,使用最多数据统计,从10多秒,变成了1秒多。已经可以接受。

结论:第一次做这种SQL优化,看到成果,还是很开心的。如果还有其它优化方式,请大神指教。。。

原文地址:https://www.cnblogs.com/feiyangbahu/p/12481687.html