本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使百万级、千万级数据表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果)。希望读者能够理解SQL的执行过程,并根据过程优化,走上自己的"成金之路"
 
需要优化的查询:使用explain
     出现了Using temporary;
     有分页时出现了Using filesort则表示使用不了索引,需要根据下面的技巧来调整语句
     rows过多,或者几乎是全表的记录数;
     key 是 (NULL);
     possible_keys 出现过多(待选)索引。
 
1.使用explain语法,对SQL进行解释,根据其结果进行调优:
     MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果:
          a.EXPLAIN 结果中,第一行出现的表就是驱动表
 
          b.对驱动表可以直接排序,对非驱动表(的字段排序)需要对循环查询的合并结果(临时表)进行排序(Important!),即using temporary;
 
          c. [驱动表] 的定义为:1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表];2)未指定联接条件时,行数少的表为[驱动表](Important!)。
 
          d.优化的目标是尽可能减少JOIN中Nested Loop的循环次数,以此保证:永远用小结果集驱动大结果集(Important!)!:A JOIN B,A为驱动,A中每一行和B进行循环JOIN,看是否满足条件,所以当A为小结果集时,越快。
          
          e.NestedLoopJoin实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复
 
2.两表JOIN优化:
     a.当无order by条件时,根据实际情况,使用left/right/inner join即可,根据explain优化 ;
     b.当有order by条件时,如select * from a inner join b where 1=1 and other condition order by a.col;使用explain解释语句;
     1)如果第一行的驱动表为a,则效率会非常高,无需优化;
     2)否则,因为只能对驱动表字段直接排序的缘故,会出现using temporary,所以此时需要使用STRAIGHT_JOIN明确a为驱动表,来达到使用a.col上index的优化目的;或者使用left join且Where条件中不含b的过滤条件,此时的结果集为a的全集,而STRAIGHT_JOIN为inner join且使用a作为驱动表
 
3.多表JOIN优化:
     a.无order by条件时,根据实际情况,使用left/right/inner join即可,根据explain优化;
     b.有order by a.col条件时,所有join必须为left join,且每个join字段都创建索引,同时where条件中只能有a表的条件,即将其它表的数据关联到a中形成一张大表,再对a的全集进行过滤;
          如果不能全使用left join,则需灵活使用STRAIGHT_JOIN及其它技巧,以时间排序为例:
               1)数据入库按照平台时间入库,自然a的数据都按时间有序;
SELECT c.*, r.HYPERVISOR_HOST_NAME hostname, r.HOST_IP FROM trust_monitor c STRAIGHT_JOIN res_node r ON c.res_node_id = r.ID STRAIGHT_JOIN am_assets a ON r.ASSET_ID = a.ID AND a.status = 58 STRAIGHT_JOIN se_role s ON a.DEPT_FLAG = s.ROLE_ORG AND s.ROLE_ID IN (32,33,36,41) where c.STATUS = 58 and c.changed_type = 79 limit 1,10;
 
SELECT c.*, r.HYPERVISOR_HOST_NAME hostname, r.HOST_IP FROM trust_monitor c inner JOIN res_node r ON c.res_node_id = r.ID INNER JOIN am_assets a ON r.ASSET_ID = a.ID AND a.status = 58 INNER JOIN se_role s ON a.DEPT_FLAG = s.ROLE_ORG AND s.ROLE_ID IN (32,33,36,41) where c.STATUS = 58 and c.changed_type = 79 order by c.changed_time limit 1,10;
两者结果一致
 
4.误区:
     a.视图只是屏蔽或者高效集合多表数据的一种方法,视图与表JOIN,不会起到任何效果
 
参考:

MySQL百万级、千万级数据多表关联SQL语句调优的更多相关文章

  1. MySQL千万级多表关联SQL语句调优

    本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化.   需要优化的查询:使用explain      出现了Using temporary:       ...

  2. mysql 遍历所有的库并根据表和sql语句备份

    建库.用户语句 create database test_hb; create user ' test_hb'@'%' identified by '123456'; grant all privil ...

  3. MySQL 百万级分页优化

    MySQL 百万级分页优化 http://www.jb51.net/article/31868.htm 一般刚开始学SQL的时候,会这样写 : , ; 但在数据达到百万级的时候,这样写会慢死 : , ...

  4. mysql 百万级数据库优化方案

    https://blog.csdn.net/Kaitiren/article/details/80307828 一.百万级数据库优化方案 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 wher ...

  5. MYSQL百万级数据,如何优化

    MYSQL百万级数据,如何优化     首先,数据量大的时候,应尽量避免全表扫描,应考虑在 where 及 order by 涉及的列上建立索引,建索引可以大大加快数据的检索速度.但是,有些情况索引是 ...

  6. MySQL数据库-表操作-SQL语句(一)

    1. 数据库操作与存储引擎 1.1   数据库和数据库对象 数据库对象:存储,管理和使用数据的不同结构形式,如:表.视图.存储过程.函数.触发器.事件等. 数据库:存储数据库对象的容器. 数据库分两种 ...

  7. mysql从一个表中拷贝数据到另一个表中sql语句

    这一段在找新的工作,今天面试时,要做一套题,其中遇到这么一句话,从一个表中拷贝所有的数据到另一个表中的sql是什么? 原来我很少用到,也没注意过这个问题,面试后我上网查查,回来自己亲手写了写,测试了下 ...

  8. MySQL创建民族表的SQL语句

    MySQL创建民族表的SQL语句 CREATE TABLE `nation` ( `id` ) unsigned NOT NULL AUTO_INCREMENT, `nation` ) NOT NUL ...

  9. MySql update inner join!MySql跨表更新 多表update sql语句?如何将select出来的部分数据update到另一个表里面?

    项目中,评论数,关注数等数据,是实时更新的.+1,-1 这种. 有的时候,可能统计不准确. 需要写一个统计工具,更新校准下. 用Java写SQL和函数,代码很清晰,方便扩展,但是太慢了. 为了简单起见 ...

随机推荐

  1. Eclipse 创建Android 模拟器失败:no cpu/abi system image available for this target

    (从网上搜了一个使用Android 4.4 API 20编译的图片) 这是因为SDK中没有模拟器使用的操作系统镜像. 如果项目使用API 19编译,则SDK中的system-images文件夹下,需要 ...

  2. springboot和mybatis之thymleaf整合简单插入用户数据

    编写mapper接口和对应的mapper.xml文件,注意对应的注解 @Mapper @Repository public interface StudentMapper { void insertS ...

  3. DBHelper类

    import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import ja ...

  4. java基础-- 之类型转换 和 一些运算符

    ---   首先   看一个 Scanner  类 import java.util.Scanner; public class TestScanner { public static void ma ...

  5. PHP+ajax实现二级联动

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. node.js中fs文件系统模块的使用

    node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法 ...

  7. 第一个用IDEA写的程序——“前言中不允许有内容”

    "前言中不允许有内容" 这是用IDEA写的第一个程序-- 它出现了一些问题 让人很难过 希望有人可以帮助解答,谢谢 程序是这样子的 运行完是这样显示的

  8. MySQL数据查询之单表查询

    单表查询 简单查询 - 创建表 DROP TABLE IF EXISTS `person`; CREATE TABLE `person` ( `id` ) NOT NULL AUTO_INCREMEN ...

  9. leveldb 源码编译 vs版本

    为什么要windows版本? 因为方便调试跟进 VS的体验真的很不错. 搜索了一段时间才发现GITHUB有windows版本的leveldb 但是使用VS编译也有不少坑 可以下载网络上的其他朋友的版本 ...

  10. Unittest中TestCase类中定义的几个特殊方法

    1.setUp():每个测试方法运行前运行,测试前的初始化工作: 2.tearDown():每个测试方法运行结束后运行,测试后的清理工作: 3.setUpClass():所有的测试方法运行前运行,单元 ...