首先我们对于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. 异常:Invalid character found in the request target. The valid characters are defined in RFC 3986

    一.背景 事情是这样的,前几天做一个基本的数据库“增删改查”的需求,前端传参的方式是“JSON字符串”,后端接收到此参数后,使用阿里巴巴fastjson进行解析,然后入库.需求很简单吧,但是偏偏遇到问 ...

  2. SIP中From ,Contact, Via 和 Record-Route/Route

    转载:http://eadgar.blogbus.com/logs/374635.html 注意:以下内容适用于SIP消息中,在具体的应用环境中,例如IMS,每个消息头都有其他独特的意义,但不会和以下 ...

  3. element ui的照片墙 默认显示照片

    参考地址: element ui的照片墙 默认显示照片 照片显示的数据格式是:[{name: '', url: ''}],:file-list=""默认显示的图片 实际项目开发中需 ...

  4. 通过mysql 连接远程数据库时,输入密码后,提示10060错误

    能提示输入密码,说明网络能够连接,而且能连到服务器.输入密码后提示错误,说明应该是权限问题 解决方法: ​一.进入mysql数据库命令行 ​二.输入use mysql; ​三.设置root账号密码为1 ...

  5. Delphi 类类型和对象

  6. Delphi 声明特性

  7. Django—Form组件

    Django From简介 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比 ...

  8. Windows&Appium&Python自动化测试-Appium安装

    一.安装node.js 官方下载地址为:https://nodejs.org/en/download 傻瓜式安装即可,安装完成后,CMD中运行node -v查看版本号 输入npm 出现如上图信息,表示 ...

  9. RHEL8 创建本地YUM存储库

    yum 的好处及本地yum的好处不在本文讨论范畴,本文针对rhel8中的新功能yum做简要介绍和配置,在 RHEL 8中分为两个存储库: BaseOS 应用程序流(AppStream) BaseOS中 ...

  10. VSS使用技巧

    理由很简单:迁出锁定!之所以强调这个,是因为这方面吃过的亏太多,我举几个例子:1.比如两个程序员增加了同一个功能,但是实现方法不同,比如甲:func1,乙 func2,两者代码也不一样第二个人在迁入代 ...