一:Join 的问题?

  - 在实际生产中,使用 join 一般会集中在以下两类:

    - DBA 不让使用 Join ,使用 Join 会有什么问题呢?

    - 如果有两个大小不同的表做 join,应该用哪个表做驱动表呢?

二:数据准备

  • CREATE TABLE `t2` (
    `id` int() NOT NULL,
    `a` int() DEFAULT NULL,
    `b` int() DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `a` (`a`)
    ) ENGINE=InnoDB; CREATE TABLE `t1` (
    `id` int() NOT NULL,
    `a` int() DEFAULT NULL,
    `b` int() DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `a` (`a`)
    ) ENGINE=InnoDB;

    - 建立 t1,t2 两个完全相同的表,t1 表中写入 100 条数据,t2 表中 写入 1000 条数据。

三:Index Nested-Loop Join(NLJ) (被驱动表有索引的情况选择)

  - 语句

    - 为了避免Mysql选择驱动表对于分析的影响,改用 straight_join 让 MySQL 使用固定的连接方式执行查询。

    - t1 是驱动表,t2 是被驱动表。

    - select * from t1 straight_join t2 on (t1.a=t2.a);

  - 执行流程

    - 在这条语句里,被驱动表 t2 的字段 a 上有索引,join 过程用上了这个索引

    - 从表 t1 中读入一行数据 R;

    - 从数据行 R 中,取出 a 字段到表 t2 里去查找;

    - 取出表 t2 中满足条件的行,跟 R 组成一行,作为结果集的一部分;

    - 重复执行步骤 1 到 3,直到表 t1 的末尾循环结束。

    - 

  - 小结

    - 这个过程是先遍历表 t1,然后根据从表 t1 中取出的每行数据中的 a 值,去表 t2 中查找满足条件的记录。

    - 在形式上,这个过程很像写程序时的嵌套查询类似,并且可以用上被驱动表的索引,所以我们称之为“Index Nested-Loop Join”,简称 NLJ。

    - 整个过程, 总扫描行数是 200(t1 200 + t2 索引树200)

四:Block Nested-Loop Join(NLJ)(被驱动表无索引选择)

  - 语句

    -  select * from t1 straight_join t2 on (t1.a=t2.b);

    - 由于表 t2 的字段 b 上没有索引,因此在执行流程时,每次到 t2 去匹配的时候,就要做一次全表扫描。

  - 流程

    - 把表 t1 的数据读入线程内存 join_buffer 中,由于我们这个语句中写的是 select *,因此是把整个表 t1 放入了内存;

    - 扫描表 t2,把表 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回。

    - 

  - 小结

    - 可以看到,在这个过程中,对表 t1 和 t2 都做了一次全表扫描,因此总的扫描行数是 1100。

    - 由于 join_buffer 是以无序数组的方式组织的,因此对表 t2 中的每一行,都要做 100 次判断,总共需要在内存中做的判断次数是:100*1000=10 万次。

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

五:总结

  - 能不能使用 join ?

    - 如果可以使用 Index Nested-Loop Join 算法,也就是说可以用上被驱动表上的索引,其实是没问题的;

    - 如果使用 Block Nested-Loop Join 算法,扫描行数就会过多。

      - 尤其是在大表上的 join 操作,这样可能要扫描被驱动表很多次,会占用大量的系统资源。所以这种 join 尽量不要用。

  - 如果要使用 join,应该选择大表做驱动表还是选择小表做驱动表?

    - 在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。

《Mysql - 到底可不可以使用 Join ?》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. python多线程实现抓取网页

    Python实现抓取网页 以下的Python抓取网页的程序比較0基础.仅仅能抓取第一页的url所属的页面,仅仅要预定URL足够多.保证你抓取的网页是无限级别的哈,以下是代码: ##coding:utf ...

  2. 浏览器的多线程和js的单线程--前端易混淆知识科普(一)

    问题:js是单线程的,页面是从上往下加载的,那么是不是第一个js没加载完成,第二个js就不加载?然后,引申出来一个问题就是,那css和图片呢?这之间的加载有相互影响吗? 1.什么是线程?什么是进程?什 ...

  3. EF:插入记录失败,提示当 IDENTITY_INSERT 设置为 OFF 时,不能向表中的标识列插入显式值

    EF忽然报错:增加记录时,提示当 IDENTITY_INSERT 设置为 OFF 时,不能向表 '...' 中的标识列插入显式值.真奇怪,添加记录方法一向好地地,从没出过错.要出错,那也是Update ...

  4. Unable to update auto-refresh reference 'microsoft.codedom.providers.dotnetcompilerplatform.dll'.

    Unable to update auto-refresh reference 'microsoft.codedom.providers.dotnetcompilerplatform.dll'. Ca ...

  5. B1299 [LLH邀请赛]巧克力棒 博弈论

    这个题一看就是nim游戏的变形.每次先手取出巧克力就是新建一个nim,但假如先手取一个为0的而且无论后手怎么取剩下的都无法为零就行了.然后用dfs跑. 题干: Description TBL和X用巧克 ...

  6. struts2什么情况用#和EL表达示

    1:struts2标签使用中,什么时候用#,什么时候可以不用# 值栈中的对象的不使用#,非值栈中的对象使用#如果不理解值栈的作用,简单点理解:当前action,或者处于action链中的action所 ...

  7. discuz的cutstr函数

    function cutstr($string, $length, $dot = ' ...') { if(strlen($string) <= $length) { return $strin ...

  8. 1.1输出“hello,world”

    #include<iostream> using namespace std; int main() { cout<<"Hello, World!"< ...

  9. HTML--文本域,支持多行文本输入

    当用户需要在表单中输入大段文字时,需要用到文本输入域. 语法: <textarea rows="行数" cols="列数">文本</texta ...

  10. BZOJ 4828 DP+BFS

    被一道简单BFS坑了这么长时间我也是hhh了 //By SiriusRen #include <bits/stdc++.h> using namespace std; ,,):d(D),x ...