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优化实践之快速匹配的更多相关文章

  1. MySQL的JOIN(四):JOIN优化实践之快速匹配

    这篇博文讲述如何优化扫描速度.我们通过MySQL的JOIN(二):JOIN原理得知了两张表的JOIN操作就是不断从驱动表中取出记录,然后查找出被驱动表中与之匹配的记录并连接.这个过程的实质就是查询操作 ...

  2. Mysql中Join用法及优化

    Join的几种类型 笛卡尔积(交叉连接) 如果A表有n条记录,B表有m条记录,笛卡尔积产生的结果就会产生n*m条记录.在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者直接用f ...

  3. 单机数据库优化的一些实践(mysql)

    数据库优化有很多可以讲,按照支撑的数据量来分可以分为两个阶段:单机数据库和分库分表,前者一般可以支撑500W或者10G以内的数据,超过这个值则需要考虑分库分表.另外,一般大企业面试往往会从单机数据库问 ...

  4. 重新学习MySQL数据库12:从实践sql语句优化开始

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a724888/article/details/79394168 本文不堆叠网上海量的sql优化技巧或 ...

  5. 022:SQL优化--JOIN算法

    目录 一. SQL优化--JOIN算法 1.1. JOIN 写法对比 2. JOIN的成本 3. JOIN算法 3.1. simple nested loop join 3.2. index nest ...

  6. Apache Phoenix的Join操作和优化

    估计Phoenix中支持Joins,对很多使用Hbase的朋友来说,还是比较好的.下面我们就来演示一下. 首先看一下几张表的数据: Orders表: OrderID CustomerID ItemID ...

  7. 35 | join语句怎么优化?

    在上一篇文章中,我和你介绍了 join 语句的两种算法,分别是 Index Nested-Loop Join(NLJ) 和 Block Nested-Loop Join(BNL). 我们发现在使用 N ...

  8. 35 怎么优化join

    35 怎么优化join 上一篇介绍了join的两种算法:nlj和bnl create table t1(id int primary key, a int, b int, index(a)); cre ...

  9. paip.sql索引优化----join 代替子查询法

    paip.sql索引优化----join 代替子查询法 作者Attilax ,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.n ...

随机推荐

  1. codevs 1094 FBI树 2004年NOIP全国联赛普及组 x

                         题目描述 Description 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串. ...

  2. 重启php7.0-fpm

    /etc/init.d/php7.0-fpm restart

  3. luogu4212

    P4212 外太空旅行 题目描述 在人类的触角伸向银河系的边缘之际,普通人上太空旅行已经变得稀松平常了.某理科试验班有n个人,现在班主任要从中选出尽量多的人去参加一次太空旅行活动. 可是n名同学并不是 ...

  4. 笔记本在安装Windows+Linux双系统后,进入Windows时花屏的解决办法

    问题:在笔记本安装双系统(Windows7+Ubuntu14.04)[先安装Windows,后安装Ubuntu]后,进入Windows时出现了花屏. 问题原因:笔记本只有集显,在系统启动时会先加载Ub ...

  5. HDU 5795 A Simple Nim ——(Nim博弈 + 打表)

    题意:在nim游戏的规则上再增加了一条,即可以将任意一堆分为三堆都不为0的子堆也视为一次操作. 分析:打表找sg值的规律即可. 感想:又学会了一种新的方法,以后看到sg值找不出规律的,就打表即可~ 打 ...

  6. JVM-GC算法(三)-分代收集算法

    对象分类 上次已经说过,分代收集算法是针对对象的不同特性,而使用合适的算法,这里面并没有实际上的新算法产生.与其说分代收集算法是第四个算法,不如说它是对前三个算法的实际应用.  首先我们来探讨一下对象 ...

  7. Orcal数据类型总结

    一.Oracle中的varchar2类型 我们在Oracle数据库存储的字符数据一般是用VARCHAR2.VARCHAR2既分PL/SQL Data Types中的变量类型,也分Oracle Data ...

  8. 安装 redis manager

    安装文档在redis manager 的官方文档上有,这里做个笔记.官网地址:https://snapcraft.io/redis-desktop-manager 截图1: 可以选择自己的系统,根据里 ...

  9. CSS 浮动 float 属性

    浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止. 由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样. 请看下图,当把框 1 向右浮动时,它 ...

  10. WCF绑定(Binding)

    一个Binding由一个有序的binding元素栈所组成,其中的每一个元素都指定了连接到ServiceEndpoint的一个方面.在这个栈中的最底两层都是必须要有的.最底下的一层是传输binding元 ...