MYSQL join 优化 --JOIN优化实践之快速匹配
MySQL的JOIN(四):JOIN优化实践之快速匹配
优化原则:小表驱动大表,被驱动表建立索引有效,驱动表建立索引基本无效果。A left join B :A是驱动表,B是被驱动表;A right join B,B是驱动表,A是被驱动表,A jion B,sql优化器会自动优化,实现小表驱动大表。
这篇博文讲述如何优化扫描速度。我们通过MySQL的JOIN(二):JOIN原理得知了两张表的JOIN操作就是不断从驱动表中取出记录,然后查找出被驱动表中与之匹配的记录并连接。这个过程的实质就是查询操作,想要优化查询操作,建索引是最常用的方式。那索引怎么建呢?我们来讨论下,首先插入测试数据。

CREATE TABLE t1 (
id INT PRIMARY KEY AUTO_INCREMENT,
type INT
);
SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 110000 |
+----------+
CREATE TABLE t2 (
id INT PRIMARY KEY AUTO_INCREMENT,
type INT
);
SELECT COUNT(*) FROM t2;
+----------+
| COUNT(*) |
+----------+
| 100 |
+----------+

左连接
左连接中,左表是驱动表,右表是被驱动表。想要快速查找被驱动表中匹配的记录,所以我们可以在右表建索引,从而提高连接性能。

-- 首先两个表都没建索引
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.type=t2.type;
+----+-------+------+------+--------+----------------------------------------------------+
| id | table | type | key | rows | Extra |
+----+-------+------+------+--------+----------------------------------------------------+
| 1 | t1 | ALL | NULL | 110428 | NULL |
| 1 | t2 | ALL | NULL | 100 | Using where; Using join buffer (Block Nested Loop) |
+----+-------+------+------+--------+----------------------------------------------------+
-- 尝试在左表建立索引,改进不大
CREATE INDEX idx_type ON t1(type);
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.type=t2.type;
+----+-------+-------+----------+--------+----------------------------------------------------+
| id | table | type | key | rows | Extra |
+----+-------+-------+----------+--------+----------------------------------------------------+
| 1 | t1 | index | idx_type | 110428 | Using index |
| 1 | t2 | ALL | NULL | 100 | Using where; Using join buffer (Block Nested Loop) |
+----+-------+-------+----------+--------+----------------------------------------------------+ -- 尝试在右表建立索引,效果拔群,Using index!!!
DROP INDEX idx_type ON t1;
CREATE INDEX idx_type ON t2(type);
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.type=t2.type;
+----+-------+------+---------------+----------+--------+-------------+
| id | table | type | possible_keys | key | rows | Extra |
+----+-------+------+---------------+----------+--------+-------------+
| 1 | t1 | ALL | NULL | NULL | 110428 | NULL |
| 1 | t2 | ref | idx_type | idx_type | 1 | Using index |
+----+-------+------+---------------+----------+--------+-------------+

右连接
右连接中,右表是驱动表,左表是被驱动表,想要快速查找被驱动表中匹配的记录,所以我们可以在左表建索引,从而提高连接性能。

DROP INDEX idx_type ON t2;
-- 两个表都没有索引
EXPLAIN SELECT * FROM t1 RIGHT JOIN t2 ON t1.type=t2.type;
+----+-------+------+------+--------+----------------------------------------------------+
| id | table | type | key | rows | Extra |
+----+-------+------+------+--------+----------------------------------------------------+
| 1 | t2 | ALL | NULL | 100 | NULL |
| 1 | t1 | ALL | NULL | 110428 | Using where; Using join buffer (Block Nested Loop) |
+----+-------+------+------+--------+----------------------------------------------------+ -- 在右边建立索引,改进不大
CREATE INDEX idx_type ON t2(type);
EXPLAIN SELECT * FROM t1 RIGHT JOIN t2 ON t1.type=t2.type;
+----+-------+-------+---------------+----------+--------+----------------------------------------------------+
| id | table | type | possible_keys | key | rows | Extra |
+----+-------+-------+---------------+----------+--------+----------------------------------------------------+
| 1 | t2 | index | NULL | idx_type | 100 | Using index |
| 1 | t1 | ALL | NULL | NULL | 110428 | Using where; Using join buffer (Block Nested Loop) |
+----+-------+-------+---------------+----------+--------+----------------------------------------------------+ -- 尝试在左边建立索引,效果拔群!
DROP INDEX idx_type ON t2;
CREATE INDEX idx_type ON t1(type);
EXPLAIN SELECT * FROM t1 RIGHT JOIN t2 ON t1.type=t2.type;
+----+-------+------+---------------+--------------+------+-------------+
| id | table | type | possible_keys | ref | rows | Extra |
+----+-------+------+---------------+--------------+------+-------------+
| 1 | t2 | ALL | NULL | NULL | 100 | NULL |
| 1 | t1 | ref | idx_type | test.t2.type | 5 | Using index |
+----+-------+------+---------------+--------------+------+-------------+

内连接
我们知道,MySQL Optimizer会对内连接做优化,不管谁内连接谁,都是用小表驱动大表,所以如果要优化内连接,可以在大表上建立索引,以提高连接性能。
另外注意一点,在小表上建立索引时,MySQL Optimizer会认为用大表驱动小表效率更快,转而用大表驱动小表。
对内连接小表驱动大表的优化策略不清楚的话,可以看MySQL的JOIN(三):JOIN优化实践之内循环的次数

DROP INDEX idx_type ON t1;
-- 两个表都没有索引,t2驱动t1
EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t1.type=t2.type;
+----+-------+------+------+--------+----------------------------------------------------+
| id | table | type | key | rows | Extra |
+----+-------+------+------+--------+----------------------------------------------------+
| 1 | t2 | ALL | NULL | 100 | NULL |
| 1 | t1 | ALL | NULL | 110428 | Using where; Using join buffer (Block Nested Loop) |
+----+-------+------+------+--------+----------------------------------------------------+
-- 在t2表上建立索引,MySQL的Optimizer发现后,用大表驱动了小表
CREATE INDEX idx_type ON t2(type);
EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t1.type=t2.type;
+----+-------+------+----------+--------+-------------+
| id | table | type | key | rows | Extra |
+----+-------+------+----------+--------+-------------+
| 1 | t1 | ALL | NULL | 110428 | Using where |
| 1 | t2 | ref | idx_type | 1 | Using index |
+----+-------+------+----------+--------+-------------+ -- 在t1表上建立索引,再加上t1是大表,符合“小表驱动大表”的原则,性能比上面的语句要好
DROP INDEX idx_type ON t2;
CREATE INDEX idx_type ON t1(type);
EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t1.type=t2.type;
+----+-------+------+---------------+----------+------+-------------+
| id | table | type | possible_keys | key | rows | Extra |
+----+-------+------+---------------+----------+------+-------------+
| 1 | t2 | ALL | NULL | NULL | 100 | Using where |
| 1 | t1 | ref | idx_type | idx_type | 5 | Using index |
+----+-------+------+---------------+----------+------+-------------+

三表连接
上面都是两表连接,三表连接也是一样的,找出驱动表和被驱动表,在被驱动表上建立索引,即可提高连接性能。
总结
想要从快速匹配的角度优化JOIN,首先就是找出谁是驱动表,谁是被驱动表,然后在被驱动表上建立索引即可。
MYSQL join 优化 --JOIN优化实践之快速匹配的更多相关文章
- MySQL的JOIN(四):JOIN优化实践之快速匹配
这篇博文讲述如何优化扫描速度.我们通过MySQL的JOIN(二):JOIN原理得知了两张表的JOIN操作就是不断从驱动表中取出记录,然后查找出被驱动表中与之匹配的记录并连接.这个过程的实质就是查询操作 ...
- Mysql中Join用法及优化
Join的几种类型 笛卡尔积(交叉连接) 如果A表有n条记录,B表有m条记录,笛卡尔积产生的结果就会产生n*m条记录.在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者直接用f ...
- 单机数据库优化的一些实践(mysql)
数据库优化有很多可以讲,按照支撑的数据量来分可以分为两个阶段:单机数据库和分库分表,前者一般可以支撑500W或者10G以内的数据,超过这个值则需要考虑分库分表.另外,一般大企业面试往往会从单机数据库问 ...
- 重新学习MySQL数据库12:从实践sql语句优化开始
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a724888/article/details/79394168 本文不堆叠网上海量的sql优化技巧或 ...
- 022:SQL优化--JOIN算法
目录 一. SQL优化--JOIN算法 1.1. JOIN 写法对比 2. JOIN的成本 3. JOIN算法 3.1. simple nested loop join 3.2. index nest ...
- Apache Phoenix的Join操作和优化
估计Phoenix中支持Joins,对很多使用Hbase的朋友来说,还是比较好的.下面我们就来演示一下. 首先看一下几张表的数据: Orders表: OrderID CustomerID ItemID ...
- 35 | join语句怎么优化?
在上一篇文章中,我和你介绍了 join 语句的两种算法,分别是 Index Nested-Loop Join(NLJ) 和 Block Nested-Loop Join(BNL). 我们发现在使用 N ...
- 35 怎么优化join
35 怎么优化join 上一篇介绍了join的两种算法:nlj和bnl create table t1(id int primary key, a int, b int, index(a)); cre ...
- paip.sql索引优化----join 代替子查询法
paip.sql索引优化----join 代替子查询法 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.n ...
随机推荐
- Confluence 6 评论一个文件
无论是一个图片 —— 例如一个模拟的新市场计划需要反馈,还是一个 PDF 文件,一个演讲稿,或者任何你可以在 Confluence 中预览的文件.你可以在预览的的任何位置放置一个热点然后添加你的评论后 ...
- TTTTTTTTTTTTTT CF 95 B 构造4,7幸运数字 贪心 构造 string
B. Lucky Numbers time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- Js模块化开发--seajs和gruntJs
1.Seajs库 解决开发中的冲突依赖等问题,提供代码可维护性. SeaJS 是由玉伯开发的一个遵循 CommonJS 规范的模块加载框架,可用来轻松愉悦地加载任意 JavaScript 模块和css ...
- linux命令---vi编辑器快速定位行数
linux命令—vi编辑器快速定位行数.删除当前行.和删除当前行后面的全部内容 1.vi 编辑器如何快速定位到第N行 命令方式下 :n http://bbs.chinaunix.net/thread- ...
- linux如何模糊查找一个文件
在当前目录下搜索指定文件: find . -name test.txt 在当前目录下模糊搜索文件: find . -name '*.txt' 在当前目录下搜索特定属性的文件: find . -amin ...
- 化学结构SDF文件
参考博客 第一行:一般作为分子名字,如 Levetiracetam 第二行:注释,ChemDraw06111413562D 第三行:一般是空行 第四行:是原子个数 键的个数等的起始行. M END所在 ...
- zookeeper系列(七)zookeeper的序列化及通讯协议
作者:leesf 掌控之中,才会成功:掌控之外,注定失败.原创地址http://www.cnblogs.com/leesf456/p/6091208.html尊重作者原创,奇文共欣赏,大家共同学 ...
- elasticsearch与kibana安装过程(linux)
elasticsearch与kibana安装 下载 Elasticsearch 官网:https://www.elastic.co/,elastic search应用本质就是一个jvm进程,所以需要J ...
- (转)linux中wget未找到命令
转:https://blog.csdn.net/djj_alice/article/details/80407769 在装数据库的时候发现无法使用wget命令,提示未找到命令,如图所示 那是因为没有安 ...
- Thymeleaf Multiple Template Locations using Spring Boot
1. Overview In this tutorial, we'll see how we can define multiple template locations using Thymelea ...