IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Mysql Join原理分析 -> 正文阅读

[大数据]Mysql Join原理分析

mysql> select * from t1 left join t2 on t1.name=t2.name

说明:

  1. t1 表为驱动表
  2. t2 表为被驱动表
  3. 小表为驱动表

join 语句执行过程中,驱动表是走全表扫描,而被驱动表是走树搜索。

当name 在t2 表中有索引时:
通过Index Nested-Loop Join 算法,执行过程:

  1. 从 t1 表中读入一行数据 R;
  2. 从数据行 R 中,取出 name 字段到表 t2 里去查找;
  3. 通过name 字段值去查找 t2 表中满足的值,通过嵌套循环的方式去匹配数据,取出 t2 中满足条件的行,跟 R 组成一行,作为结果集的一部分;
  4. 循环1到3步骤,直到t1 表数据循环完。

当name 在t2 表中没有索引时:
通过 Simple Nested-Loop Join 算法,执行过程:
简单的说就是 假如 t1 和 t2 表中 各有100 条数据,则循环的次数就是 100 * 100 = 10000 次。当然mysql 没有使用这种算法,而使用的是 Block Nested-Loop Join 算法去计算的。

通过Block Nested-Loop Join 算法 执行过程:

  1. 把表 t1 的数据读入线程内存 join_buffer 中,由于我们这个语句中写的是 select *,因此是把整个表 t1 放入了内存;
  2. 扫描表 t2,把表 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回。
    所以会在内存中计算100 * 100 = 10000 次。
    两个算法是一样的,不过Block Nested-Loop Join算法是在内存中计算,所以速度上会快很多,性能也更好。

join_buffer

join_buffer 的大小是由参数 join_buffer_size 设定的,默认值是 256k。如果放不下表 t1的所有数据话,策略很简单,就是分段放。
执行过程如下:

  1. 扫描表 t1,顺序读取数据行放入 join_buffer 中,假如放完第 88 行 join_buffer 满了,继续第 2 步;
  2. 扫描表 t2,把 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回;
  3. 清空 join_buffer;
  4. 继续扫描表 t1,顺序读取最后行数据放入 join_buffer 中,继续执行第 2 步。
    结论:join_buffer_size 越大,一次可以放入的行越多,分成的段数也就越少,对被驱动表的全表扫描次数就越少。

要不要使用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 不够大的时候(这种情况更常见),应该选择小表做驱动表。
    所以,这个问题的结论就是,总是应该使用小表做驱动表。

小结:

  1. 如果可以使用被驱动表的索引,join 语句还是有其优势的;
  2. 不能使用被驱动表的索引,只能使用 Block Nested-Loop Join 算法,这样的语句就尽量不要使用;
  3. 在使用 join 的时候,应该让小表做驱动表。

Join 算法总结
不论是Index Nested-Loop Join 还是 Block Nested-Loop Join 都是在Simple Nested-Loop Join的算法的基础上进行优化,这里 Index Nested-Loop Join 和Nested-Loop Join 算法是分别对Join过程中循环匹配次数和IO 次数两个角度进行优化。
Index Nested-Loop Join 是通过索引的机制减少内层表的循环匹配次数达到优化效果,而Block Nested-Loop Join 是通过一次缓存多条数据批量匹配的方式来减少外层表的IO次数,同时也减少了内层表的扫表次数,通过 理解join 的算法原理我们可以得出以下表连接查询的优化思路。
1、永远用小结果集驱动大结果集(其本质就是减少外层循环的数据数量)
2、为匹配的条件增加索引(减少内层表的循环匹配次数)
3、增大join buffer size的大小(一次缓存的数据越多,那么内层包的扫表次数就越少)
4、减少不必要的字段查询(字段越少,join buffer 所缓存的数据就越多)

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:28:20  更:2022-04-01 23:29:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:07:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码