join left loke mysql_MySQL百万级、千万级数据多表关联SQL语句调优

点击上方 "程序员小乐"关注, 星标或置顶一起成长

每天凌晨00点00分, 第一时间与你相约

每日英文

I'd rather be able to see all of my faults clearly than live my life pretending to be perfect.

宁可活得对自己的缺点清清楚楚,也不愿一辈子假装完美。

每日掏心话

时间,总在我们得志的时候溜得飞快,在我们失意的时候放慢脚步。

来自:成金之路 | 责编:乐乐

链接:cnblogs.com/uttu/p/6384541.html

4e680d44e161fc1a888eaa20a3b98310.png

程序员小乐(ID:study_tech)第 890 次推文 图源:百度

往日回顾:干掉 "FastJson"

正文

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

希望读者能够理解SQL的执行过程,并根据过程优化,走上自己的"成金之路"

需要优化的查询:

使用explain
出现了Using temporary;

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

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

  • key 是 (NULL);

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

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

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

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

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

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

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

  • 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解释语句;

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

  • 否则,因为只能对驱动表字段直接排序的缘故,会出现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,不会起到任何效果

参考:

cnblogs.com/zhengyun_ustc/p/slowquery1.html
huoding.com/2013/06/04/261

89373d4d62e75215b1678d7ae571ac51.png

欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。

猜你还想看

阿里、腾讯、百度、华为、京东最新面试题汇集

项目实践中的一些性能优化指南

JAVA 泛型中的通配符 T,E,K,V,?

Spring IOC 知识点总结,写得太好了!

关注订阅号「程序员小乐」,收看更多精彩内容
嘿,你在看吗?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值