暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

MySQL 派生表优化实例 性能提升209倍

原创 aisql 2023-01-09
1537

1、发现问题

像往常一样去RDS 的监控平台检查慢SQL
其中有一个SQL很意思,可以拿来讲讲。因为表数据很少。语句也很短。

我们先来整体看一下语句。然后再讲表结构与数据量

select count(0) from customer a left join ( select b.* from custlabel b join label c on b.tid=c.tid and b.labelid=c.labelid where b.tid=585184 ) t on t.tid=a.tid and t.custid=a.custid where a.tid=585184 and a.custid != 0 and t.tid is null

上面语句执行时间达到了 13s

查看一下三个表的数据量
image.png

三个表的数据量都很少。执行时间却达到了13s

2、检查与解决问题

看执行计划
image.png

我们看到了问题。t表是一个派生表。 派生表与customer 表的关联走的是Block Nested Loop 证明没有使用索引关联

我们继续看派生表的执行计划

explain select b.* from custlabel b join label c on b.tid=c.tid and b.labelid=c.labelid where b.tid=585184

image.png

可以看到。MySQL遵循了小表做驱动表的原则 这里使用了只有13行的label表做驱动表

我们继续看看两个表的主键或索引
custlabel 表的主键为 PRIMARY KEY (tid,custid,labelid), 刚好就是外层customer 的关联条件

我们强制让custlabel 走驱动表试试

explain select count(0) from customer a left join ( select b.* from custlabel b straight_join label c on b.tid=c.tid and b.labelid=c.labelid where b.tid=585184 ) t on t.tid=a.tid and t.custid=a.custid where a.tid=585184 and a.custid != 0 and t.tid is null

image.png

我们可以看到 执行计划的Block Nested Loop消失了。证明关联字段使用上了索引

最终执行时间为 0.062s

3、总结

执行时间从13s 降低到了0.062s 性能提升了209倍

在8.0版本以前和派生表的join 一定要注意是否能走上索引
但在8.0版本这个语句不需要优化。customer与派生表的join 会直接走hash方式来join.

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论