0

0

MySQL中join语句如何优化

PHPz

PHPz

发布时间:2023-06-03 09:31:58

|

1367人浏览过

|

来源于亿速云

转载

Simple Nested-Loop Join

我们来看一下当进行 join 操作时,mysql是如何工作的。常见的 join 方式有哪些?

MySQL中join语句如何优化

如图,当我们进行连接操作时,左边的表是驱动表,右边的表是被驱动表

Simple Nested-Loop Join 这种连接操作是从驱动表中取出一条记录然后逐条匹配被驱动表的记录,如果条件匹配则将结果返回。接着,继续匹配驱动表的下一条记录,直到驱动表的所有数据都被匹配完

因为每次从驱动表取数据比较耗时,所以MySQL并没有采用这种算法来进行连接操作

Block Nested-Loop Join

MySQL中join语句如何优化

为了避免每次从驱动表取数据耗时,我们可以将一批数据一次性从驱动表取出,并在内存中进行匹配操作。这批数据匹配完毕,再从驱动表中取一批数据放到内存中,直到驱动表的数据全都匹配完毕

批量取数据能减少很多IO操作,因此执行效率比较高,这种连接操作也被MySQL采用

对了,这块内存在MySQ中有一个专有的名词,叫做 join buffer,我们可以执行如下语句查看 join buffer 的大小

show variables like '%join_buffer%'

MySQL中join语句如何优化

把我们之前用的 single_table 表搬出来,基于 single_table 表创建2个表,每个表插入1w条随机记录

CREATE TABLE single_table (
    id INT NOT NULL AUTO_INCREMENT,
    key1 VARCHAR(100),
    key2 INT,
    key3 VARCHAR(100),
    key_part1 VARCHAR(100),
    key_part2 VARCHAR(100),
    key_part3 VARCHAR(100),
    common_field VARCHAR(100),
    PRIMARY KEY (id),
    KEY idx_key1 (key1),
    UNIQUE KEY idx_key2 (key2),
    KEY idx_key3 (key3),
    KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;

create table t1 like single_table;
create table t2 like single_table;

如果直接使用 join 语句,MySQL优化器可能会选择表 t1 或者 t2 作为驱动表,这样会影响我们分析sql语句的过程,所以我们用 straight_join 让mysql使用固定的连接方式执行查询

select * from t1 straight_join t2 on (t1.common_field = t2.common_field)

运行时间为0.035s

MySQL中join语句如何优化

执行计划如下

MySQL中join语句如何优化

在Extra列中看到了 Using join buffer ,说明连接操作是基于 Block Nested-Loop Join 算法

Index Nested-Loop Join

了解了 Block Nested-Loop Join 算法之后,可以看到驱动表的每条记录会把被驱动表的所有记录都匹配一遍,非常耗时,能不能提高一下被驱动表匹配的效率呢?

估计这种算法你也想到了,就是给被驱动表连接的列加上索引,这样匹配的过程就非常快,如图所示

MySQL中join语句如何优化

我们来看一下基于索引列进行连接执行查询有多快?

select * from t1 straight_join t2 on (t1.id = t2.id)

执行时间为0.001秒,可以看到比基于普通的列进行连接快了不止一个档次

云模块网站管理系统3.1.03
云模块网站管理系统3.1.03

云模块_YunMOK网站管理系统采用PHP+MYSQL为编程语言,搭载自主研发的模块化引擎驱动技术,实现可视化拖拽无技术创建并管理网站!如你所想,无限可能,支持创建任何网站:企业、商城、O2O、门户、论坛、人才等一块儿搞定!永久免费授权,包括商业用途; 默认内置三套免费模板。PC网站+手机网站+适配微信+文章管理+产品管理+SEO优化+组件扩展+NEW Login界面.....目测已经遥遥领先..

下载

MySQL中join语句如何优化

执行计划如下

MySQL中join语句如何优化

驱动表的记录并不是所有列都会被放到 join buffer,只有查询列表中的列和过滤条件中的列才会被放入 join buffer,因此我们不要把 * 作为查询列表,只需要把我们关心的列放到查询列表就好了,这样可以在 join buffer 中放置更多的记录

如何选择驱动表?

知道了 join 的具体实现,我们来聊一个常见的问题,即如何选择驱动表?

如果是 Block Nested-Loop Join 算法:

  • 当 join buffer 足够大时,谁做驱动表没有影响

  • 当 join buffer 不够大时,应该选择小表做驱动表(小表数据量少,放入 join buffer 的次数少,减少表的扫描次数)

如果是 Index Nested-Loop Join 算法

假设驱动表的行数是M,因此需要扫描驱动表M行

每次从被驱动表中获取一行数据时,需要先查找索引a,然后再查找主键索引。被驱动表的行数为N。每次搜索一颗树近似复杂度是以2为底N的对数,所以在被驱动表上查一行的时间复杂度是 2 ∗ l o g 2 N 2*log2^N 2∗log2N

驱动表的每一行数据都要到被驱动表上搜索一次,整个执行过程近似复杂度为 M + M ∗ 2 ∗ l o g 2 N M + M*2*log2^N M+M∗2∗log2N

显然M对扫描行数影响更大,因此应该让小表做驱动表。当然这个结论的前提是可以使用被驱动表的索引

总而言之,我们让小表做驱动表即可

当 join 语句执行的比较慢时,我们可以通过如下方法来进行优化

  • 进行连接操作时,能使用被驱动表的索引

  • 小表做驱动表

  • 增大 join buffer 的大小

  • 不要用 * 作为查询列表,只返回需要的列

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

676

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

346

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1095

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

357

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

675

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

571

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

414

2024.04.29

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.8万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 792人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号