MySQL千万级多表关联SQL语句调优

本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使千万级表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果)。

 

需要优化的查询:使用explain

     出现了Using temporary;

     有分页时出现了Using filesort则表示使用不了索引,需要根据下面的技巧来调整语句

     rows过多,或者几乎是全表的记录数;

     key 是 (NULL);

     possible_keys 出现过多(待选)索引。

 

1.使用explain语法,对SQL进行解释,根据其结果进行调优:

     MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果:

          a.EXPLAIN 结果中,第一行出现的表就是驱动表

 

          b.对驱动表可以直接排序,对非驱动表(的字段排序)需要对循环查询的合并结果(临时表)进行排序(Important!),即using temporary;

 

          c. [驱动表] 的定义为:1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表];2)未指定联接条件时,行数少的表为[驱动表](Important!)。

 

          d.优化的目标是尽可能减少JOIN中Nested Loop的循环次数,以此保证:永远用小结果集驱动大结果集(Important!)!:A JOIN B,A为驱动,A中每一行和B进行循环JOIN,看是否满足条件,所以当A为小结果集时,越快。

          

          e.NestedLoopJoin实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复

 

2.两表JOIN优化:

     a.当无order by条件时,根据实际情况,使用left/right/inner join即可,根据explain优化 ;

     b.当有order by条件时,如select * from a inner join b where 1=1 and other condition order by a.col;使用explain解释语句;

     1)如果第一行的驱动表为a,则效率会非常高,无需优化;

     2)否则,因为只能对驱动表字段直接排序的缘故,会出现using temporary,所以此时需要使用STRAIGHT_JOIN明确a为驱动表,来达到使用a.col上index的优化目的;或者使用left join且Where条件中不含b的过滤条件,此时的结果集为a的全集,而STRAIGHT_JOIN为inner join且使用a作为驱动表

 

3.多表JOIN优化:

     a.无order by条件时,根据实际情况,使用left/right/inner join即可,根据explain优化;

     b.有order by a.col条件时,所有join必须为left join,且每个join字段都创建索引,同时where条件中只能有a表的条件,即将其它表的数据关联到a中形成一张大表,再对a的全集进行过滤;

          如果不能全使用left join,则需灵活使用STRAIGHT_JOIN及其它技巧,以时间排序为例:

               1)数据入库按照平台时间入库,自然a的数据都按时间有序;

SELECT c.*, r.HYPERVISOR_HOST_NAME hostname, r.HOST_IP FROM trust_monitor c STRAIGHT_JOIN res_node r ON c.res_node_id = r.ID STRAIGHT_JOIN am_assets a ON r.ASSET_ID = a.ID AND a.status = 58 STRAIGHT_JOIN se_role s ON a.DEPT_FLAG = s.ROLE_ORG AND s.ROLE_ID IN (32,33,36,41) where c.STATUS = 58 and c.changed_type = 79 limit 1,10;

 

SELECT c.*, r.HYPERVISOR_HOST_NAME hostname, r.HOST_IP FROM trust_monitor c inner JOIN res_node r ON c.res_node_id = r.ID INNER JOIN am_assets a ON r.ASSET_ID = a.ID AND a.status = 58 INNER JOIN se_role s ON a.DEPT_FLAG = s.ROLE_ORG AND s.ROLE_ID IN (32,33,36,41) where c.STATUS = 58 and c.changed_type = 79 order by c.changed_time limit 1,10;

两者结果一致

 

4.误区:

     a.视图只是屏蔽或者高效集合多表数据的一种方法,视图与表JOIN,不会起到任何效果

 

参考:

     http://www.cnblogs.com/zhengyun_ustc/p/slowquery1.html

     http://huoding.com/2013/06/04/261

http://www.cnblogs.com/uttu/p/6384541.html

时间: 2024-10-31 10:13:38

MySQL千万级多表关联SQL语句调优的相关文章

生产环境大型sql语句调优实战第一篇(一)

在生产环境中有一条sql语句的性能极差,在早晨非高峰时段运行抽取数据,平均要花费40分钟,有时候竟然要跑10个多小时.sql语句比较长,需要点耐心往下看.我对表的数据量都做了简单的说明. 首先拿到sql语句,一看到关联的表有一长串,而且都是很大的表.如果性能很差,可能和走全表扫描有关,还有可能和多表关联时,表的查取顺序也有一定的关系. SELECT   DISTINCT CA.L9_CONVERGENCE_CODE AS ATB2,                 CU.CUST_SUB_TYP

生产环境sql语句调优实战第八篇

生产环境中的sql语句执行时间是很关键的性能指标,如果某个sql语句执行几个小时,优化以后几分钟,几十秒的话.会有很大的成就感,同时如果某个sql语句执行10秒,能够优化到1秒,感觉提升的幅度不是很大,但是如果这条语句执行极为频繁的话,那这种调优还是更有成就感的. 执行时间是sql调优的一把标尺,但是同时也需要考虑到系统资源的平衡. 今天在系统中发现一条sql语句执行时间很长.平均一个查询要执行一个半小时左右,而且系统的资源消耗极大. 需要说明的service_details 是数据量过亿的表.

mysql千万级数据库表优化?

1.数据的容量:1-3年内会大概多少条数据,每条数据大概多少字节: 2.数据项:是否有大字段,那些字段的值是否经常被更新: 3.数据查询SQL条件:哪些数据项的列名称经常出现在WHERE.GROUP BY.ORDER BY子句中等: 4.数据更新类SQL条件:有多少列经常出现UPDATE或DELETE 的WHERE子句中: 5.SQL量的统计比,如:SELECT:UPDATE+DELETE:INSERT=多少? 6.预计大表及相关联的SQL,每天总的执行量在何数量级? 7.表中的数据:更新为主的

生产环境大型sql语句调优实战第一篇(二)

继续昨天的部分,上一篇的链接为: http://blog.itpub.net/23718752/viewspace-1217012/ 对这条大sql的性能瓶颈进行了分析.主要瓶颈在于一个很大的业务表,数据量在亿级.如果通过时间条件来过滤,会有5%以内的数据被过滤出来. 但是没有时间相关的索引字段,所以会走全表扫描,在目前的产品线中,这个大分区表的索引时严格控制的,所以最后经过测试和比对,还是考虑加并行来提高数据的查取速度. --查找性能瓶颈,根据反馈,查取的数据其实并不错,可能在几千条以内的样子

生产环境sql语句调优实战第二篇

在生产环境通过sql monitor监控到有一条sql执行效率很差.执行了大约5个小时,得到的sql monitor报告如下: Global Information: EXECUTING Instance ID : 1 Buffer Gets IO Requests Database Time Wait Activity . 40M . 17M . . 8450s . . . 100% Session : PRODUSER(14:22343) SQL ID : fkzafpjs28d6d SQL

生产环境sql语句调优实战第九篇

生产环境中有一些sql语句是不定时炸弹,不声不响的运行着,可能相关的表很大,运行时间达数小时甚至数天. 上周在生产环境中发现一条sql语句,运行时间几乎是按照天来计算的.看到这种sql语句,就希望能够马上能够找到立竿见影的效果,不过欲速则不达,需要做不少工作.一定要反复验证可行. sql语句的运行情况如下: SQL Execution ID : 16777217  Execution Started : 10/18/2014 11:46:30  First Refresh Time : 10/1

生产环境sql语句调优实战第十篇

陆陆续续写了九篇关于生产环境sql语句的调优案例,发现了不少问题,可能有些问题回头来看是比较低级的错误,稍加改动就能够运行在秒级,有些可能是在秒级到毫秒级的小步提升等等,不管调优的改进多大,从dba的角度来看,好多问题都是基于资源来调优的,比如添加索引,降低IO,降低CPU消耗,提高CPU利用率等等.如果有时候从业务角度来下下功夫,可能某种程度上效果要更好于基于资源/代价的调优. 最近客户反馈有几条sql语句IO消耗很高,希望我们能够给提点建议. sql语句很短,但是运行时间在9秒左右.运行频率

生产环境sql语句调优实战第三篇

生产环境有一条sql语句执行比较频繁,占用了大量的cpu资源.原本执行需要花费11秒.在一次排查中引起了我的注意,决定看看cpu消耗到底在哪儿? sql语句是比较简单的,通过查询SUBSCRIBER_FA_V是一个视图.在视图中关联了几个和业务核心表. SELECT TO_CHAR(SUBSCRIBER_NO) SUBSCRIBER_ID,        SUB_STATUS,        SUB_STS_RSN_CD,        TO_CHAR(SUB_STATUS_DATE, 'yyy

生产环境sql语句调优实战第四篇

生产中有一条sql语句消耗了大量的cpu资源,执行时间在18秒左右, Session : PRODBUSER (1560:61133) SQL ID : 1hg2wcuapy3y3 SQL Execution ID : 16871963 Execution Started : 07/21/2014 12:30:20 First Refresh Time : 07/21/2014 12:30:24 Last Refresh Time : 07/21/2014 12:30:37 Duration :