mysql单单写join_MySQL系列之Join大法
1. Index Nested-Loop Join
概念解释:
假设有t1,t2两张表,在join连接的时候,t1表驱动t2表,t1走的全部扫描,t2表使用了索引,
则这个时候join就使用了“index nested-loop join”算法,简称:NLJ。
NLJ执行的流程如下:
Index Nested-Loop Join 算法的执行流程
2. Block Nested-Loop Join
基于上面t1表和t2表,join连接,t1表和t2表都没有命中索引,都是走的全部扫描。这个
时候Join使用的是“Block Nested-Loop Join”算法,简称:BNL。
BNL算法的流程如下:
Block Nested-Loop Join 算法的执行流程
在explain分析语句的时候,extra附加信息中会出现“Using join buffer (Block Nested Loop)”。
join_buffer是由参数join_buffer_size决定的。默认是256k。如果放不下表 t1
的所有数据话,策略很简单,就是分段放。
流程大概是:
取t1表的数据,放入join_buffer中,如果join buffer满了,就扫描t2表的数据,跟join buffer
的数据进行对比,满足join条件的作为结果集返回;清空join buffer,继续上面的过程。
能否使用Join?
1. 如果可以使用 Index Nested-Loop Join 算法,也就是说可以用上被驱动表上的索引,
其实是没问题的;
2. 如果使用 Block Nested-Loop Join 算法,扫描行数就会过多。尤其是在大表上的 join
操作,这样可能要扫描被驱动表很多次,会占用大量的系统资源。所以这种 join 尽量不
要用。
如果要使用 join,应该选择大表做驱动表还是选择小表做驱动表?
1. 如果是 Index Nested-Loop Join 算法,应该选择小表做驱动表;
2. 如果是 Block Nested-Loop Join 算法:
在 join_buffer_size 足够大的时候,是一样的;
在 join_buffer_size 不够大的时候(这种情况更常见),应该选择小表做驱动表。
这个问题的结论就是,总是应该使用小表做驱动表。
注意:join慢的时候,尽量跳大join_buffer_size的值。
优化Join
1. 优化NLJ算法
Multi-Range Read 优化算法 (MRR)。这个优化的主要目的是尽量使用顺序读盘。
如果随着辅助索引(二级索引) a 的值递增顺序查询的话,主键索引id 的值就变成随机的,
那么就会出现随机访问,性能相对较差。虽然“按行查”这个机制不能改,但是调整查询的顺序,
还是能够加速的。这就是 MRR 优化的设计思路。
加入了MRR优化的执行流程如下:
1. 根据索引 a,定位到满足条件的记录,将 id 值放入 read_rnd_buffer 中 ;
2. 将 read_rnd_buffer 中的 id 进行递增排序;
3. 排序后的 id 数组,依次到主键 id 索引中查记录,并作为结果返回。
read_rnd_buffer 的大小是由 read_rnd_buffer_size 参数控制的。
启用MRR算法:
set optimizer_switch="mrr_cost_based=off"
Batched Key Access (BKA) 算法
MySQL 在 5.6 引入的,是对 NLJ 算法的优化。
NLJ 算法优化后的 BKA 算法的流程如下:
Batched Key Acess 流程
启用 BKA 算法:
set optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';
前两个参数的作用是要启用 MRR。这么做的原因是,BKA 算法的优化要依赖于MRR。
BNL 算法的优化
优化的常见做法是,给被驱动表的 join 字段加上索引,把 BNL 算法转成 BKA 算法。
但是如果无法在被驱动表上加索引,那么:
考虑使用临时表,使用临时表的大致思路是:
1. 把表 t2 中满足条件的数据放在临时表 tmp_t 中;
2. 为了让 join 使用 BKA 算法,给临时表 tmp_t 的字段 b 加上索引;
3. 让表 t1 和 tmp_t 做 join 操作。
SQL语句为:
create temporary table temp_t(id int primary key, a int, b int, index(b))engine=innodb;
insert into temp_t select * from t2 where b>=1 and b<=2000;
select * from t1 join temp_t on (t1.b=temp_t.b);
总体来看,不论是在原表上加索引,还是用有索引的临时表,我们的思路都是让 join 语句
能够用上被驱动表上的索引,来触发 BKA 算法,提升查询性能。
上面如果不适用临时表进行优化,那么还有其他方式进行优化?
我们可以自己实现在业务端。实现流程大致如下:
1. select * from t1;取得表 t1 的全部 1000 行数据,在业务端存入一个 hash 结构,
比如 C++ 里的 set、PHP 的数组这样的数据结构。
2. select * from t2 where b>=1 and b<=2000; 获取表 t2 中满足条件的 2000 行
数据。
3. 把这 2000 行数据,一行一行地取到业务端,到 hash 结构的数据表中寻找匹配的数
据。满足匹配的条件的这行数据,就作为结果集的一行。
关于临时表的几个问题:
1. binlog_format=row,那么跟临时表有关的语句,就不会记录到binlog 里。只在
binlog_format=statment/mixed 的时候,binlog 中才会记录临时表的操作。
2. 在使用临时表的时候,最后最好要写上 DROP TEMPORARY TABLE,删除临时表
3. 临时表只对本session会话可见,对其他的session不可见。
mysql单单写join_MySQL系列之Join大法相关推荐
- mysql update inner join_mysql update inner join错误
update a set a.city=b.city FROM(SELECT * FROM zhujiagewang WHERE collecttime='2016-10-27′ AND city I ...
- mysql的full join_mysql实现full join
展开全部 Oracle .DB2.SQL Server.PostgreSQL 支持 Full JOIN 但是 MySQL 是不支持的. 可以通过 LEFT JOIN + UNION + RI ...
- mysql入门很简单系列视频-学习笔记
mysql入门很简单系列视频-学习笔记 视频链接:mysql入门很简单系列视频 https://www.bilibili.com/video/av14920200/ 以前主要就了解DDL.DML.DC ...
- 手写webpack系列一:了解认识loader-utils
Created By JishuBao on 2019-03-29 12:38:22 Recently revised in 2019-04-01 12:38:22 欢迎大家来到技术宝的掘金世界, ...
- 自己动手写Docker系列 -- 5.7实现通过容器制作镜像
简介 在上篇中我们实现了rm命令,删除存在的容器,本篇中,将完善之前的文件系统隔离,实现容器与容器之间的文件系统隔离 源码说明 同时放到了Gitee和Github上,都可进行获取 Gitee: htt ...
- MySQL怎么运行的系列(十)Innodb中的锁:记录锁、临键锁、间隙锁、意向锁
本系列文章目录 展开/收起 MySQL怎么运行的系列(一)mysql体系结构和存储引擎 MySQL怎么运行的系列(二)Innodb缓冲池 buffer pool 和 改良版LRU算法 Mysql怎么运 ...
- MySQL怎么运行的系列(五)Innodb表空间(table space)、区(extent)和段(segment)
本系列文章目录 展开/收起 MySQL怎么运行的系列(一)mysql体系结构和存储引擎 MySQL怎么运行的系列(二)Innodb缓冲池 buffer pool 和 改良版LRU算法 Mysql怎么运 ...
- MySQL怎么运行的系列(十一)快照读、锁定读、半一致性读 和 加锁语句分析
本系列文章目录 展开/收起 MySQL怎么运行的系列(一)mysql体系结构和存储引擎 MySQL怎么运行的系列(二)Innodb缓冲池 buffer pool 和 改良版LRU算法 Mysql怎么运 ...
- MySQL怎么运行的系列(二)Innodb缓冲池 buffer pool 和 改良版LRU算法
本系列文章目录 展开/收起 MySQL怎么运行的系列(一)mysql体系结构和存储引擎 MySQL怎么运行的系列(二)Innodb缓冲池 buffer pool 和 改良版LRU算法 MySQL怎么运 ...
最新文章
- ARM架构和ARM核区别和联系
- html5点击显示展开列表,HTML5 - 如何折叠和展开复杂的表格元素
- varchar 保存英文中文区别。
- 爬虫图片href是html图片,xpath爬虫实例,爬取图片网站百度盘地址和提取码
- 五个值得放收藏夹吃灰的Go CheatSheet 站点
- Java中类方法的快速入门
- hbase 核心知识
- 《JQuery 能干点啥~》第四讲 html() 与 text()的赋值比较
- build.gradle文件介绍
- linux实用技巧:ubuntu18.04安装samba服务器实现局域网文件共享
- 英语心理测试脸型软件,心理测试:脸型分析自己
- alert#40;1#41; to xss.haozi.me with #0x02
- Git还能这样玩?居然被他玩出了新花样
- 一种简单的PCB加温电路设计
- 分享一些程序员必备网站
- webstorm直接运行js
- 关于打印机能够搜到但是无法连接的解决办法
- 这些问题才是阻碍蓝牙耳机音质的元凶,2021什么牌子蓝牙耳机靠谱?
- 程序媛眼中的程序员,piupiu~
- hippo4j启动登录不上
热门文章
- java zip文件操作,java 关于 zip 文件 的 基本操作
- quill鼠标悬浮 出现提示_外设报道——DELUX多彩M618X垂直鼠标颠覆创新
- Android开发之git命令创建tag提交远程仓库的方法(图文教程)
- 关于 VC 执行顺序
- python统计提取数量_python中统计计数的几种方法和Counter的介绍
- Envoy Proxy构建控制平面指南
- V神:区块链跨链技术大规模应用将在一到两年内爆发
- tp5.0行为的用法,可以存入json数据,方便读取数据。
- opensuse x64下编译Ice源码(以编译c++为例)
- Medoo 开源项目发布,超轻量级的PHP SQL数据库框架