[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
写在前面的话:
不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程;
不要求每个人一定知道线上(现在或未来)哪张表数据量大,哪张表数据量小;
但把mysql客户端(如SQLyog,如HeidiSQL)放在桌面上,时不时拿出来 explain 一把,这是一种美德!
在实例讲解之前,我们先回顾一下联表查询的基础知识。
——联表查询的基础知识——
引子:为什么第一个查询using temporary,第二个查询不用临时表呢?
下面两个查询,它们只差了一个order by,效果却迥然不同。
第一个查询:
EXPLAIN extended
SELECT ads.id
FROM ads, city
WHERE
city.city_id = 8005
AND ads.status = 'online'
AND city.ads_id=ads.id
ORDER BY ads.id desc
执行计划为:
id select_type table type possible_keys key key_len ref rows filtered Extra
------ ----------- ------ ------ -------------- ------- ------- -------------------- ------ -------- -------------------------------
1 SIMPLE city ref ads_id,city_id city_id 4 const 2838 100.00 Using temporary; Using filesort
1 SIMPLE ads eq_ref PRIMARY PRIMARY 4 city.ads_id 1 100.00 Using where
第二个查询:
EXPLAIN extended
SELECT ads.id
FROM ads,city
WHERE
city.city_id =8005
AND ads.status = 'online'
AND city.ads_id=ads.id
ORDER BY city.ads_id desc
------ ----------- ------ ------ -------------- ------- ------- -------------------- ------ -------- ---------------------------
1 SIMPLE city ref ads_id,city_id city_id 4 const 2838 100.00 Using where; Using filesort
1 SIMPLE ads eq_ref PRIMARY PRIMARY 4 city.ads_id 1 100.00 Using where
1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表];
2)未指定联接条件时,行数少的表为[驱动表](Important!)。
永远用小结果集驱动大结果集(Important!)!
——实例讲解——
explainSELECT mb.id, ……FROMmb LEFT JOIN mbei ON mb.id=mbei.mb_id INNER JOINu ON mb.uid=u.uidWHERE 1=1ORDER BY mbei.apply_time DESClimit 0,10
------ ----------- ------ ------ -------------- -------------- ------- ------------------- ------- --------------------------------------------
1 SIMPLE mb index userid userid 4 (NULL) 6060455 Using index; Using temporary; Using filesort
1 SIMPLE mbei eq_ref mb_id mb_id 4 mb.id 1
1 SIMPLE u eq_ref PRIMARY PRIMARY 4 mb.uid 1 Using index
explainSELECT mb.id……FROM mb JOIN mbei ON mb.id=mbei.mb_id INNER JOINu ON mb.uid=u.uidWHERE 1=1ORDER BY mbei.apply_time DESClimit 0,10
------ ----------- ------ ------ -------------- ------- ------- ---------------------------- ------ --------------
1 SIMPLE mbei ALL mb_id (NULL) (NULL) (NULL) 13383 Using filesort
1 SIMPLE mb eq_ref PRIMARY,userid PRIMARY 4 mbei.mb_id 1
1 SIMPLE u eq_ref PRIMARY PRIMARY 4 mb.uid 1 Using index
优化第一步之分支1:根据驱动表的字段排序,好吗?
explainSELECT mb.id……FROM mb LEFT JOIN mbei ON mb.id=mbei.mb_id INNER JOINu ON mb.uid=u.uidWHERE 1=1ORDER BY mb.id DESClimit 0,10
------ ----------- ------ ------ -------------- -------------- ------- ------------------- ------ -----------
1 SIMPLE mb index userid PRIMARY 4 (NULL) 10
1 SIMPLE mbei eq_ref mb_id mb_id 4 mb.id 1 Using index
1 SIMPLE u eq_ref PRIMARY PRIMARY 4 mb.uid 1 Using index
优化第二步:去除所有JOIN,让MySQL自行决定!
explainSELECT mb.id……FROM mb,mbei,u
WHERE
mb.id=mbei.mb_id
and mb.uid=u.user_id
order by mbei.apply_time desc
limit 0,10
立竿见影,驱动表一样是小表 mbei:
------ ----------- ------ ------ -------------- ------- ------- ---------------------------- ------ --------------
1 SIMPLE mbei ALL mb_id (NULL) (NULL) (NULL) 13388 Using filesort
1 SIMPLE mb eq_ref PRIMARY,userid PRIMARY 4 mbei.mb_id 1
1 SIMPLE u eq_ref PRIMARY PRIMARY 4 mb.uid 1 Using index
最后的总结:
不要过于相信你的运气!不要相信你的开发环境里SQL的执行速度!请拿起 explain 武器,如果你看到以下现象,请优化:
- 出现了Using temporary;
- rows过多,或者几乎是全表的记录数;
- key 是 (NULL);
- possible_keys 出现过多(待选)索引。
记住,explain 是一种美德!

[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定的更多相关文章
- 【转】[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
转自:http://zhengyun-ustc.iteye.com/blog/1942797 写在前面的话: 不要求每个人一定理解 联表查询(join/left join/inner join等)时的 ...
- 了解MySQL联表查询中的驱动表,优化查询,以小表驱动大表
一.为什么要用小表驱动大表 1.驱动表的定义 当进行多表连接查询时, [驱动表] 的定义为: 1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表] 2)未指定联接条件时,行数少的表为[驱动表 ...
- 【explain】MySQL联表查询中的驱动表
写在前面 1.不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程 2.不要求每个人一定知道线上(现在或未来)哪张表数据量大,哪张表数据量小 3 ...
- MySQL多表查询之外键、表连接、子查询、索引
MySQL多表查询之外键.表连接.子查询.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为 ...
- python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)
12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefaul ...
- mysql重点,表查询操作和多表查询
表单查询 1. 完整的查询语句语法 select distinct(* or 字段名 or 四则运算 )from 表名 where 条件 group by 条件 having 条件 order by ...
- 如何让in/exists 子查询(半连接)作为驱动表?
一哥们问我,怎么才能让子查询作为驱动表? SQL如下: select rowid rid from its_car_pass7 v where 1 = 1 and pass_datetime > ...
- 关于mysql,需要掌握的基础(一):CRUD、存储引擎、单表查询相关、多表查询join、事务并发、权限管理等等
目录 关于mysql,需要掌握的基础(一): 1.了解数据库sql.数据库系统.数据库管理系统的概念. 2.了解DDL.DML.DQL语句是什么? 3.了解存储引擎.存储引擎[InnoDB 和 MyI ...
- MySQL数据库学习笔记(六)----MySQL多表查询之外键、表连接、子查询、索引
本章主要内容: 一.外键 二.表连接 三.子查询 四.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复 ...
随机推荐
- 62.Android之各分辨率定义的图片规格
转载:http://www.nljb.net/default/Android%E4%B9%8B%E5%90%84%E5%88%86%E8%BE%A8%E7%8E%87%E5%AE%9A%E4%B9%8 ...
- Android热身:通过网络获取资源并更新UI组件
Android热身:通过网络获取资源并更新UI组件 目标 点击"发送请求"按钮,下载某网页的html源码,并显示在TextView控件上:点击"清空",清除Te ...
- 系统补丁更新导致MVC3.0.0升级到3.0.1的问题解决
在更新了系统补丁之后,会不知觉的将MVC3.0.0升级到MVC3.0.1的问题,解决的思路如下: 1.全部MVC引用使用NuGet进行包的管理. 2.单独把MVC库抽离出来,然后放在单独的项目文件夹, ...
- Apache日志配置参数详细说明
Apache日志按时间分段记录 在apache的配置文件httpd.conf中找到ErrorLog logs/error_log及CustomLog logs/access_log common Li ...
- app基本信息
1.获取设备信息 NSLog(@"设备名称:%@",[[UIDevice currentDevice] systemName]); NSLog(@"版本号:%@" ...
- [Xcode 自带svn的使用]
xcode自带svn的使用 1.代码中 某文件后面有 “M” 标记,表示该文件已被修改,需要commit. (右键该文件 -> source control -> c ...
- RabbitMQ 通过记日志来看routingkey
RoutingKey 每个项目都需要记录日志,日志则一般会分为多种级别,常见的是 Info.debug.warn.Error 对于前三种日志,在项目运行中会产生大量的消息,但是一般多数情况下是不会用到 ...
- 王高利:Linux__apache,安装,报错解决
今日编译apache时出错:#./configure --prefix--检查编辑环境时出现:checking for APR... noconfigure: error: APR not found ...
- 给linux添加yum源。
在玩linux的过程中,经常会下载一些源码包.软件大多是国外人写的,由于众所周知的原因,网络下载很慢. 所以想到了更新yum源的方法. 我的linux版本是CentOS6.3的. 以下参考百度. 1, ...
- 理解与应用css中的display属性
理解与应用css中的display属性 display属性是我们在前端开发中常常使用的一个属性,其中,最常见的有: none block inline inline-block inherit 下面, ...