ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL性能优化之复杂SQL优化实践

2022-02-25 18:02:48  阅读:295  来源: 互联网

标签:tuser union address 索引 SQL MySQL 优化 select


  前几篇对于Mysql性能优化分别进行了探索阐述,本文将对前述要点进行模拟实践,如下:

  环境准备:

    新建表tuser1和tuser2:

      

    通过查询test_insert存储过程,创建类似存储过程初始化tuser1,tuser2数据:  

      select `name` from mysql.proc where db = 'xx' and `type` = 'PROCEDURE|FUNCTION'' //存储过程或函数
      show procedure|function status; //存储过程或函数

      show create procedure proc_name;
      show create function func_name;

      

       

   业务场景:tuser表按照地区分组统计求和,要求是在tuser1表和tuser2表中出现过的地区

    select address, count(*) from tuser where address in (select address from tuser1 union select address from tuser2)group by address;

   tuser中adress只有beijing,所以结果是正确的,但是这个查询花的时间太长了。修改测试数据是查询有数据看看是什么效果,还花这么长时间么?

    

     

   一样耗时较长。使用explain分析为啥耗时如此之长:

     type:为ALL 说明没有索引,全表扫描
    Using temporary:说明使用了临时表
    Using where:没有索引下推,在Server层进行了全表扫描和过滤
  第一次优化:给address加索引

      

       加索引之后速度不到原来的一半,可谓事半功倍。

      

     explain分析使用了添加的索引,但是联合查询即union还是舍弃了索引的使用,那就这点进行优化。

  第二次优化:不使用union

    select address, count(*) from tuser where address in (select distinct address from tuser1) or address in (select distinct address from tuser2)group by address; 

      

     可以看到查询时间只有个位数了,为什么呢?通过explain分析可知没有使用临时表了——这是表象,本质是union需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟;不使用当然就不存在这部分开销了。故一般不推荐使用union关键字。

   第三次优化:过滤无效数据

    还可以在优化么?通过explain分析执行计划可以看出,rows=9747263——索引只是使用了覆盖索引,说明还是几乎扫描了全表的行。

      

     可以先过滤掉不满足条件的数据是遍历tuser的数据量成数据量级减少提高效率,当然过滤的时间不能耗时否则过滤就没有意义了。

    具体使用join,left join或rignt join可以通过数据少的过滤掉数据量多的。

    select x.address, count(*) from  (select b.* from tuser1 a left join tuser b on a.address = b.address union select d.* from tuser2 c left join tuser d on c.address = d.address ) x group by x.address;

      

     此次优化使用了union,与第二次优化对比似乎可知减少遍历次数比不适用union效果更好。

  最后一次优化:派生表

        

     上次优化还是使用到了临时表,如果将将派生表写成视图,是否能提高查询效率呢?

      create view v_tuser as select b.* from tuser1 a left join tuser b on a.address = b.address union select distinct d.* from rom tuser2 c left join tuser d on c.address = d.address ;

        

      两个不同的查询语句:

         

     通过测试可以发现使用count(address),查询熟读可以是0.00sec——毫秒级。

  总结:

    优化结果:从最初的将近2分钟优化到不到1秒。

    优化总结:
      1)开启慢查询日志,定位运行慢的SQL语句
      2)利用explain执行计划,查看SQL执行情况
      3)关注索引使用情况:type
      4)关注Rows:行扫描
      5)关注Extra:没有信息最好
      6)加索引后,查看索引使用情况,index只是覆盖索引,并不算很好的使用索引
      7)如果有关联尽量将索引用到eq_ref或ref级别
      8)复杂SQL可以做成视图,视图在MySQL内部有优化,而且开发也比较友好
      9)对于复杂的SQL要逐一分析,找到比较费时的SQL语句片段进行优化

   

 

 



标签:tuser,union,address,索引,SQL,MySQL,优化,select
来源: https://www.cnblogs.com/ilovebath/p/15926812.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有