我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL之join查询如何优化

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL之join查询如何优化

这篇文章主要介绍“MySQL之join查询如何优化”,在日常操作中,相信很多人在MySQL之join查询如何优化问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL之join查询如何优化”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1. 那什么是驱动表呢?

  • 指定了联接条件时,满足查询条件的记录行数少的表为驱动表

  • 未指定联接条件时,行数少的表为驱动表(Important!)

如果你搞不清楚该让谁做驱动表、谁 join 谁,就别指定谁 left/right join 谁了,请交给 MySQL优化器 运行时决定吧。

2. 复杂的sql怎么识别驱动表呢?

按经验谈,使用EXPLAIN, 第一行出现的表就是驱动表。

3. 关联查询原理是怎样的?

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

//例: user表10000条数据,class表20条数据select * from user u left join class c u.userid=c.userid

上面sql的后果就是需要用user表循环10000次才能查询出来,而如果用class表驱动user表则只需要循环20次就能查询出来。

4. 该如如何优化?

优化的目标是尽可能减少JOIN中Nested Loop的循环次数,以此保证:永远用小结果集驱动大结果集。

排序的字段也有影响,有条原则:对驱动表可以直接排序,对非驱动表(的字段排序)需要对循环查询的合并结果(临时表)进行排序!

5. 实例

explain select * from user u left join class c on u.userid=c.userid INNER JOIN subject s on c.subjectId=s.id  WHERE 1=1 ORDER BY u.create_time DESC limit 0,10

够复杂吧。假如,user表有千万级记录,class表要少得多,从执行计划的得知驱动表(数据到千万级)。由于动用了“LEFT JOIN”,所以相当于已经指定了驱动表。

如何优化?

//优化第一步:LEFT JOIN改为JOIN,对,直接 join!explain select * from user u join class c on u.userid=c.userid INNER JOIN subject s on c.subjectId=s.id  WHERE 1=1 ORDER BY u.create_time DESC limit 0,10//优化第二步:从上面执行计划得知, 有Using temporary(临时表);Using filesort,解决方法是调整排序字段(借助前面讲过排序的原则)explain select * from user u join class c on u.userid=c.userid INNER JOIN subject s on c.subjectId=s.id  WHERE 1=1 ORDER BY c.id DESC limit 0,10

总之,sql优化中explain工具是非常重要的武器。

mysql优化(关联查询优化)

准备数据

#分类CREATE TABLE IF NOT EXISTS `class` (`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`card` INT(10) UNSIGNED NOT NULL,PRIMARY KEY (`id`));#图书CREATE TABLE IF NOT EXISTS `book` (`bookid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`card` INT(10) UNSIGNED NOT NULL,PRIMARY KEY (`bookid`)); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));

left join左外连接

MySQL之join查询如何优化

看这个分析结果发现:在 class 表上添加的索引起的作用不大。

结论: 

- **小表驱动大表**

  • - 小表:相对来说记录较少的表

  • - 大表:相对来说记录较多的表

- 驱动方式识别

  • left join:左边驱动右边(此时把小表放在左边)

  • right join:右边驱动左边(此时把小表放在右边)

- 加索引的方式:通常建议在大表(被驱动)的表加索引,效率提升更明显。

- 原因:

  • 原因1:被驱动表加了索引之后,收益更大。从 ALL -> ref

  • 原因2:外连接首先读取驱动表的全部数据,被驱动只读取满足连接条件的数据。

inner join:MySQL会自动根据表中的数据选择驱动表

MySQL之join查询如何优化

小结:

- 保证被驱动表的 join 字段被索引。join 字段就是作为连接条件的字段。

- left join 时,选择小表作为驱动表(放左边),大表作为被驱动表(放右边)

- inner join 时,mysql 会自动将小结果集的表选为驱动表。

- 子查询尽量不要放在被驱动表,衍生表建不了索引

- 能够直接多表关联的尽量直接关联,不用子查询

到此,关于“MySQL之join查询如何优化”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL之join查询如何优化

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MySQL之join查询如何优化

这篇文章主要介绍“MySQL之join查询如何优化”,在日常操作中,相信很多人在MySQL之join查询如何优化问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL之join查询如何优化”的疑惑有所帮助!
2023-07-05

MySQL之join查询优化方式

这篇文章主要介绍了MySQL之join查询优化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-12

如何优化MySQL查询

这篇文章给大家介绍如何优化MySQL查询,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。解析器和预处理器一开始,MySQL 的解析器将查询语句拆分成一系列指令并从中构建一棵“解析树”。解析器使用 MySQL 的SQL 语
2023-06-15

MySQL JOIN关联查询的原理及优化

目录1 关联查询的执行2 没有索引的算法1 关联查询的执行关联查询的执行过程是:先遍历关联表t1(驱动表,全表扫描),然后根据从表t1中取出的每行数据中的a值,去表t2(被关联表,被驱动表)中查找满足条件的记录,可以走t2的索引搜索。在形
2022-08-22

Mysql查询优化之IN子查询优化方法详解

这篇文章主要给大家介绍了关于Mysql查询优化之IN子查询优化的相关资料,需要的朋友可以参考下
2023-02-09

MySQL优化之慢查询日志

慢查询日志概述所谓慢查询日志,就是用于记录MySQL中响应时间超过设定阈值的SQL语句,通过打开慢查询开关,MySQL会将大于阈值的SQL记录在日志中,以便于分析性能。慢查询日志选项默认是关闭的,如果要开启,则需要手动设置。慢查询日志选项不建议一直开启,因为记
MySQL优化之慢查询日志
2021-08-28

MySQL如何优化查询速度

前面章节我们介绍了如何选择优化的数据类型、如何高效的使用索引,这些对于高性能的MySQL来说是必不可少的。 但这些还完全不够,还需要合理的设计查询。 如果查询写的很糟糕,即使表结构再合理、索引再合适,也是无法实现高性能的。 谈到MySQL性
2022-05-23

如何优化mysql查询速度

要优化 MySQL 查询速度,可以采取以下几种方法:使用合适的索引:在查询中使用索引可以显著提高查询速度。确保表中的字段都有适当的索引,尤其是在经常用作查询条件的字段上。避免全表扫描:尽量避免对整个表进行扫描,可以通过添加索引或优化查询语句
如何优化mysql查询速度
2024-05-23

如何优化MySQL循环查询

要优化MySQL循环查询,可以采取以下几种方法:使用JOIN操作:尽量避免在循环中进行多次查询,可以通过使用JOIN操作将多个查询合并成一个查询,减少查询次数,提高效率。使用索引:为经常被查询的字段建立索引,可以加快查询速度。同时,尽量避免
如何优化MySQL循环查询
2024-04-29

mysql优化——查询优化

这一篇mysql优化是注重于查询优化,根据mysql的执行情况,判断mysql什么时候需要优化,关于数据库开始阶段的数据库逻辑、物理结构的设计结构优化不是本文重点,下次再谈。 查看mysql语句的执行情况,判断是否需要进行优化 当感觉操作数据库查询语句速度
mysql优化——查询优化
2016-09-05

mysql in慢查询如何优化

这篇文章主要介绍“mysql in慢查询如何优化”,在日常操作中,相信很多人在mysql in慢查询如何优化问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”mysql in慢查询如何优化”的疑惑有所帮助!接下来
2022-12-30

mysql查询优化

select * from a where id in (select id from b)等价于:for select id from bfor select 8 from a where a.id = b.id当b表数据必须小于a表数据时,in优于exis
mysql查询优化
2022-02-02

MySQL如何实现跨库join查询

目录mysql实现跨库join查询同服务器的不同库不同服务器的不同库数据库跨库join方案总结MySQL实现跨库joinjs查询同服务器的不同库只需要在表名前加上db_nameselect*fromupythonserdb.user
2023-03-09

编程热搜

目录