利用子查询优化SQL

在千万级别的数据表中以一个无索引的列作为查询条件,结果可想而知,大部分情况下肯定是非常耗时。这无疑造成的结果就是,这样的慢SQL查询,轻则只是影响使用它的接口,重则在用户请求量大的情况下占满我们的数据库资源,造成生产环境业务的不能操作。所以对于大数据量的查询,我们需要建立适合的索引来优化查询。

        一般情况下,我们都会根据业务需求以及结合经验给相应的列创建合适的索引,大部分情况下都会满足我们目前的需求。然而随着业务的发展以及数据量的增长,我们即便看似都尽量使用到了有索引的列作为查询条件,但是最后SQL的查询性能还是不理想。原因可能我们还是不够了解执行一个SQ所要经历的过程,这导致我们忽略了或者没有想到还有其他的解决方案。这个时候我们不妨换个思路,先分析这个SQL的执行计划以及执行过程中资源的使用的情况,比如:

  • 通过 EXPLAIN 分析 SQL 执行计划;

  • 通过 Show Profile 分析 SQL 执行性能;

      结合这以上两种方式,具体分析我们的SQL耗时在哪里,然后对症下药重新编写我们的SQL;其中我们最意想不到的就是,在一个SQL中合理地利用一个子查询可以达到我们意向不到结果。下面是我在改造报名单中涉及“扁鹊短信需求”的功能时,一个分组统计SQL做了子查询和没有子查询的查询耗时情况对比,如下图所示:

     利用子查询优化SQL

      以上数据,我是在生产环境的查询库进行试验的,真实性可靠。无子查询的SQL的耗时受外界因素影响比较大,可能当时网络带宽好,那么耗时比较低,但是大部分情况下耗时长是居多。而有子查询的SQL整体耗时趋于稳定,查询耗时也是远低于无子查询SQL的耗时。由此可见合理的子查询可以帮助我们的SQL性能提高一个量级,其实最根本的原因还是充分利用了主键索引的效果。因此利用子查询优化SQL正好解决了我改造“扁鹊短信需求”而走ES不支持深度查询,走BD耗时长的困扰。

     目前暂定这个方案,因为尽管利用子查询减少了不少时间,但是对于一个SQL的执行时间来说,耗时还是太长了,已经是个慢SQL了。但是选择深夜去执行,而且每天执行一次,那么结果应该还是可接受的。