首先我们对于join操作,需要了解两个概念:驱动表和被驱动表。首先先给出两张表:

CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB; drop procedure idata;
delimiter ;;
create procedure idata()
begin
declare i int;
set i=1;
while(i<=1000)do
insert into t2 values(i, i, i);
set i=i+1;
end while;
end;;
delimiter ;
call idata(); create table t1 like t2;
insert into t1 (select * from t2 where id<=100)

t1数据100行,t2数据1000行,a字段有索引,b字段无索引。

select * from t1 straight_join t2 on (t1.a=t2.a);// 在执行该sql时,t1被强制性作为驱动表,而t2就是被驱动表了

  这条语句执行过程是先对t1全表扫,拿到每一行数据的a值,然后作为搜索条件到t2表里进行搜索,以为b有索引并且b的值不重复,所以认为扫表(回表)次数就是100+1000(因为走索引很快并且只要找到对应的t2的a之后只需要回表一次),ok,扫表次数:N+M。

  之后再看复杂度,首先t1的扫表次数是N,其次每一个t1的行在t2里都需要做两次索引查找操作,可以认为是N*2*logM,因此复杂度为:N+N*2*logM。

  由此可见,当小表作为驱动表时,复杂度会小很多!但是这是在被驱动表t2的a值有索引的情况下,如果没有索引,t2就只能全表扫描了,这种情况下建议立马考虑索引问题,虽然说mysql对此有它自己的优化方案:Block Nested Loop

  我们可以再看一看对于驱动表没有索引的情况下再采用上面的方式,扫表次数以及判断复杂度的不同:

  (1)扫表:t1还是继续他的N次扫表,然后t2就大有不同了,因为缺少了索引,导致只能走全表扫描也就是M次,那也就是相当暴力的N+N*M次扫表,这个时候不论大表做驱动还是小表做驱动,扫表次数都一样。。。

  (2)数据判断复杂度:t2直接全表扫,N+N*M。。

  通过上面的判断,发现做法“惊为天人”!于是乎,mysql是这样来优化的,在扫描行数上,驱动表因为一般是小表,可以一次性加载到内存中,然后把判断值的操作放到内存中执行(有索引的话,判断操作是在磁盘里走索引判断),也就是说每次都做t2的全表扫,然后这些M和每一个t1的值做匹配,也就是在扫表次数上比上一个要好很多:N+M,但是在判断的时间复杂度来看,其实还是N*M,但是由于是在内存操作,所以在时间上会弥补很多!!但是由于join_buffer的大小有限制,所以很多时候t1的数据不能一次性加载进来,所以在这个操作过程中t2表可能会被扫好几次,这个是由t1要加载到buffer几次而决定,加载的越多,t2的扫表次数越多,所以buffer的空间越大越好!!

而有关mysql决定哪些表是否是小表而来做驱动时,有他自己的选择方案:可能有些表的数据很大,但是因为有某些where条件而使得真实加载到buffer的数据很少,mysql也就很有可能选择它做小表,或者说是某些表在select后面的条件很少,例如select t1.*,t2.b  这种,因为t2所需要的数据很少,因此可以剩下更多的buffer空间,减少加载buffer的次数,所以t2也很有可能被当作小表而当作驱动表!!

对于join操作,MySQL它是咋做的?的更多相关文章

  1. MySQL JOIN操作报错问题小解

    1 问题描述 在调用一个MySQL存储过程的时候,有时候会出现下面的错误: Illigal mix of collations(gbk\_chinese\_ci, IMPLICIT) and (lat ...

  2. mysql的join操作

    一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...

  3. Code First操作Mysql数据库

    前面博客也讲了,自己做一个网站,选用的是MVC+EF Code First+MySql+EasyUI,先说下技术选型.一.为什么选择MVC? 因为之前自己做的系统大部分是webForm,MVC的之前也 ...

  4. Python自动化运维之18、Python操作 MySQL、pymysql、SQLAchemy

    一.MySQL 1.概述 什么是数据库 ? 答:数据的仓库,和Excel表中的行和列是差不多的,只是有各种约束和不同数据类型的表格 什么是 MySQL.Oracle.SQLite.Access.MS ...

  5. .NET Core Dapper操作mysql数据库

    前言 现在ORM盛行,市面上已经出现了N款不同的ORM套餐了.今天,我们不谈EF,也不聊神马黑马,就说说 Dapper.如何在.NET Core中使用Dapper操作Mysql数据库呢,让我们跟随镜头 ...

  6. 【Python之路】第十九篇--Python操作MySQL

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...

  7. (独孤九剑)---PHP操作MySQL数据库

    [一]开启mysql扩展 在PHP操作MySQL数据库之前,要保证开启了MySQL数据库扩展 若未开启,则可以将php.int文件下的php_mysql开启即可,方式为去掉前面的封号; 配置完成后要重 ...

  8. 小白两篇博客熟练操作MySQL 之 第二篇

    小白两篇博客熟练操作MySQL  之   第二篇 一. 视图 视图是一个虚拟表,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称即可获取结果集, 并可以将其当做表来使用. s ...

  9. GO学习-(23) Go语言操作MySQL + 强大的sqlx

    Go语言操作MySQL MySQL是业界常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库. Go操作MySQL 连接 Go语言中的database/sql包提供了保证SQL或类SQL数据 ...

随机推荐

  1. gperftools源码分析和项目应用 - CPU Profiler

    gperftools源码分析和项目应用 - CPU Profiler 原文:https://blog.csdn.net/yubo112002/article/details/81076821 原文链接 ...

  2. div 清除浮动的四种方法

    概述:为了解决父级元素因为子级内部高度为0的问题 (很多情况 不方便给父级元素高,因为不知道有多少内容,让里面的盒子自动撑起高度),清除浮动本质叫闭合浮动更好一些,清除浮动就是把浮动的盒子关到里面,让 ...

  3. java Calendar Date 获取指定日期所在月或年的第一天和最后一天

    一.获取传入日期所在月的第一天 public static Date getFirstDayDateOfMonth(final Date date) { final Calendar cal = Ca ...

  4. 【ASE高级软件工程】第一次结对作业

    问题定义 具体规则见:讲义.大致规则如下: N个同学(N通常大于10),每人写一个0~100之间的有理数 (不包括0或100),交给裁判,裁判算出所有数字的平均值,然后乘以0.618(所谓黄金分割常数 ...

  5. C# Winfrom 自定义控件添加图标

    Winfrom自定义控件添加自定义图标实现方式: 1.新建UserControl——略 2.寻找合适的图标文件——将文件和控件放置同一目录下(相同目录.自定义控件类名.图标文件名相同) 注:如果路径不 ...

  6. HTML5常用的语义化标签

    快速查询 article | aside | nav | section | header | footer 架构预览 nav 定义导航链接的部分 在页脚显示一个站点的导航链接,如首页.服务信息页面. ...

  7. Istio技术与实践04:最佳实践之教你写一个完整的Mixer Adapter

    Istio内置的部分适配器以及相应功能举例如下: circonus:微服务监控分析平台. cloudwatch:针对AWS云资源监控的工具. fluentd:开源的日志采集工具. prometheus ...

  8. 解读Position

    首先Position在字面讲是位置的意思,在HTML中是定位的意思,它有四种属性:分别是static是静态的,也是默认的效果,没有特别的设定,遵循基本的定位规定,不能通过z-index进行层次分级. ...

  9. windows下通过批处理脚本启动redis

    三种启动方式的特点: 第一种方式 :根目录之命令窗口启动 特点:每次启动都要进入到redis的根目录,比较繁琐,并且占用一个窗口 第二种方式:bat脚本便捷启动 特点:可放在桌面便捷启动,占用窗口 第 ...

  10. string::crbegin string::crend

    const_reverse_iterator crbegin() const noexcept;功能:crbegin是最后一个字符,crend第一个字符的前一个.迭代器向左移动是“+”,向右移动是“- ...