这篇博文讲述如何优化扫描速度。我们通过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优化实践之快速匹配 优化原则:小表驱动大表,被驱动表建立索引有效,驱动表建立索引基本无效果.A left join B :A是驱动表,B是被驱动表:A right ...

  2. Mysql慢查询定位和优化实践分享

    调优目标:提高io的利用率,减少无谓的io能力浪费. 1.打开慢查询日志定位慢sql: my.cnf: slow_query_log slow_query_log_file=mysql.slow lo ...

  3. MySQL 上亿大表优化实践

    目录 背景 分析 select xxx_record语句 delete xxx_record语句 测试 实施 索引优化后 delete大表优化为小批量删除 总结 背景 XX实例(一主一从)xxx告警中 ...

  4. MySQL的JOIN(五):JOIN优化实践之排序

    这篇博文讲述如何优化JOIN查询带有排序的情况.大致分为对连接属性排序和对非连接属性排序两种情况.插入测试数据. CREATE TABLE t1 ( id INT PRIMARY KEY AUTO_I ...

  5. MySQL的JOIN(三):JOIN优化实践之内循环的次数

    这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( i ...

  6. MySQL学习(四)Join 等开发常用的操作 --- 2019年2月

    1.查数据太多不会把内存用光 InnoDB 的数据是保存在主键索引上,然后索引树分割保存在数据页上,数据页存在内存中/磁盘.change buffer 就是先把修改操作记录,然后读数据的时候,内存没有 ...

  7. Mysql中Join用法及优化

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

  8. Mysql查询优化器之关于JOIN的优化

    连接查询应该是比较常用的查询方式,连接查询大致分为:内连接.外连接(左连接和右连接).自然连接 下图展示了 LEFT JOIN.RIGHT JOIN.INNER JOIN.OUTER JOIN 相关的 ...

  9. 一个Web报表项目的性能分析和优化实践(四):MySQL建立索引,唯一索引和组合索引

    先大致介绍下项目的数据库信息. 数据库A:主要存放的通用的表,如User.Project.Report等. 数据库B.C.D:一个项目对应一个数据库,而且这几个项目的表是完全一样的. 数据库表的特点 ...

随机推荐

  1. spring mvc4使用及json 日期转换解决方案

    spring mvc使用注解方式配制,以及对rest风格的支持,真是完美致极.下面将这两天研究到的问题做个总结,供参考.1.request对象的获取方式1:在controller方法上加入reques ...

  2. [技术]浅谈OI中矩阵快速幂的用法

    前言 矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中,矩阵的运算是数值分析领域的重要问题. 基本介绍 (该部分为入门向,非入门选手可以跳过) 由 m行n列元素排列成的矩形阵列.矩阵里的 ...

  3. nginx实现请求的负载均衡 + keepalived实现nginx的高可用

    前言 使用集群是网站解决高并发.海量数据问题的常用手段.当一台服务器的处理能力.存储空间不足时,不要企图去换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求.这种 ...

  4. Android Studio设置快捷键和背景

    1.快捷键设置 复制代码并且向下移动 向下移动代码 代码提示 代码改错 更改文件名称   alt + shift + R   2.更改背景颜色-豆绿色           来自为知笔记(Wiz)

  5. H5滚动轮播插件

      概述 JRedu 随着前端技术的发展,越来越多的H5技术被应用到实际开发中,尤其是js插件更是无处不用,本章节我们主要分享下如何去自己封装一个滚动轮播插件. 1效果图如下: 2主要功能   支持超 ...

  6. 第一个简单的python程序,模拟购物车

    第一个pyhone程序,简单的购物车功能,刚开始学习,练习下手感. #/usr/bin/env python#-*- coding:utf-8 -*- salary = int(raw_input(& ...

  7. 小球自由落体动态模拟(Position Based Simulation)

    在过去的几十年中,基于物理的三维物体动态模拟成为了计算机图形学的研究热点,其中最常见的方法是基于力(force-based)的模拟方法,比如弹簧质点模型,它把物体抽象成一系列质点以及连接这些质点的弹簧 ...

  8. 关于JS的时间控制实现动态效果及实例操作

    关于JS的时间控制 <script>        BOM   //Bowers Object Model   浏览器对象模型    setTimeout()//    延迟执行一次   ...

  9. redux深入理解之中间件(middleware)

    理解reduce函数 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. arr.reduce([callback, initi ...

  10. Spring集成RabbiMQ-Spring AMQP新特性

    上一篇<Spring集成RabbitMQ-使用RabbitMQ更方便>中,我们只需要添加响应jar的依赖,就可以写一个Spring集成RabbitMQ下非常简单收发消息的程序. 我们使用的 ...