【转】[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
转自:http://zhengyun-ustc.iteye.com/blog/1942797
写在前面的话:
不要求每个人一定理解 联表查询(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自行判定
写在前面的话: 不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程: 不要求每个人一定知道线上(现在或未来)哪张表数据量大,哪张表数据量小: ...
- 了解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.什么是外键: 主键:是唯一标识一条记录,不能有重复 ...
随机推荐
- js生成随机字符串或者随机数
//返回一个指定范围内的随机数 function createRandomNum(Min,Max){ let Range = Max - Min; let Rand = Math.random(); ...
- Java RMI(远程方法调用)开发
参考 https://docs.oracle.com/javase/7/docs/platform/rmi/spec/rmi-arch2.html http://www.cnblogs.com/wxi ...
- cocos2d-x笔记4: TextField不能删除内容,以及我的解决办法。。。
3.0正式版,win32下,TextField按下backspace键不能删除内容.网上搜了下,很早就有的问题了,正式版了竟然还不解决... 真心无力吐槽啊!!!这种巨大而又明显的Bug... 从昨天 ...
- POJ 1699 Best Sequence dfs
题目: http://poj.org/problem?id=1699 无意间A了..超时一次,加了一句 if(len > ans)return; 然后就A了,dfs题,没有太多好说的,代码写的效 ...
- Java Fx-安装E(FX)CLIPSE IDE
安装E(FX)CLIPSE IDE 本文主要介绍如何在Eclipse Mars 4.5.0版本上安装e(fx)clipse. 本文中的介绍和截图使用了纯净安装的为RCP和RAP开发者准备的Eclips ...
- OC - 正则表达式 - RegexKitLite
正则表达式使用步骤: 1. 创建正则表达式对象, 设置约束条件; NSString *pattern = @"\\d{1,3}"; NSRegularExpression *reg ...
- UIlabel - 富文本属性
1.NSKernAttributeName: @10 调整字句 kerning 字句调整 2.NSFontAttributeName : [UIFont systemFontOfSize:_fontS ...
- memcached-win32-1.4.4-14 help doc
memcached-win32-1.4.4-14 cmd打开命令窗口,转到解压的目录,输入 “memcached.exe -d install”. 使用telnet命令 验证缓存服务器是否可用.tel ...
- Android Gson使用笔记
最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson,因为之前对于protoco ...
- 启动redis出现Creating Server TCP listening socket *:6379: bind: No such file or directory
E:\redis>redis-server.exe redis.windows.conf [8564] 10 Oct 20:00:36.745 # Creating Server TCP lis ...