关于Join

如上图所示,left join和inner join的取值范围还是有很明显的不同的,看网上不少文章优化left join也不交代上下文环境,直接就是教唆把left join换成inner join,只能说是章口就莱,文体两开花...

关于笛卡尔积

简言之就是强拼,不带条件的硬拼2(多)张表,结果就是直接做乘法

SELECT * FROM a CROSS JOIN b;

SELECT * FROM a INNER JOIN b;

SELECT * FROM a,b;

SELECT * FROM a NATURE JOIN b;

SELECT * FROM a NATURA join b;

如何判断驱动表

如果没有where条件

左连接,如果没有where条件,则左表为驱动表

右连接,如果没有where条件,右表为驱动表

如果有where条件

(参照《数据库索引设计与优化》第8章内容对外表的判定应该是下面写的这个样子)

(参考读书笔记:索引读书笔记)

但是实际操作中有本地谓词的表并不一定百分百的是外表,而是由优化器来判断的

#个人实际优化过程中用的最多的还是下面这条

explain规则:explain语句结果中,第一行为驱动表(该定律适用于join;子查询的话要分情况)

性能优化相关

①选谁做驱动表

引用一个举烂了的例子,在没有过滤条件的情况下,外表有多少行就会被加载多少次;参考《索引设计与优化》这本书的说法,每次加载相当于一次随机读;

假设A表10000行,B表100行;也就是说如果用A表做驱动表会伴随着10000次随机读,而如果是B表作为驱动表,会伴随着100次随机读。

所以普遍的优化方案是小表作为外表(驱动表),用小表去驱动大表。

②创建合理的索引

选择小表驱动大表,然后在内表(被驱动的大表)的连接谓词上建立索引,使得对内表的查询走索引提高效率。这种做法最高效的就是外表是一张小表,而内表的连接谓词刚好是内表的主键。

在对这种没有查询过滤条件的语句执行explain的时候会非常不爽,因为驱动表通常是走的全表扫描;在我的测试中,如果外表上没有查询过滤条件(也就是本地谓词)的话,无论查询项是否是索引项,都是走全表。(换句话说,也就是在没有过滤条件的情况下,外表其实有没有索引对于当前语句的优化意义都不太明显(因为会走全表嘛),如果专门因为某个语句去对外表建一大堆索引的可以省省了)

#用下面的例子来解释上面2句话

m表和t表都是25W行左右,大小差距不大;根据开篇说的驱动表确立规则,无查询过滤条件的左连接,左表为驱动表;蓝框表明了这一点。

绿框的t.charge_no是t表的连接谓词,在这一列上建有一个选择性不错的索引,因此在explain的第二行可以看到内表的查询走了索引,type为ref,效率还算不错。(如果这个连接谓词是t表的主键,效率会更高)

红框处可以看到,对m表取的查询值,我们仅仅取了m.charge_no这一列,而且m.charge_no上是建有索引的,但explain的第一行粉框的ALL表明m表的查询仍然走了全表(即使是我们m表的查询列只取了建有索引的列)。

#如何让外表走索引?

方法:对外表增加过滤条件(本地谓词),并且在本地谓词上创建索引

查询过滤条件中只有t表的本地谓词,因此无论左连接还是右连接,t表都是驱动表

由于过滤条件t.partner_id和t.trade_date上建有索引,因此外表t不再走全表扫描

注意2处蓝框是有关联的,右下角的那个大蓝框里面是没有temporary的,这与接下来讨论的有关

③合理的排序

前面2张图里面的语句是我在项目中遇到的一个慢查询,本体并非前面2张图贴出的那样,区别在于order by后面跟的字段不同,原语句order by后面跟着的是一个内表字段

多表join执行时,优化器内部会先找出外表,之后会对外表进行排序;如果order by后面跟的是外表字段,则排序会在这时完成。但如果order by后面的字段是内表字段,则在所有结果集选出之后,再进行一次排序,这也就是执行计划里面Using temporary的由来了。

项目中的原语句一来没有本地谓词,二来还用内表进行排序,导致最后的执行时间达到8s之久;与研发沟通之后将语句改成用外表字段排序,执行时间所短到0.3s。

④强行指定驱动表

左右连接都可以指定驱动表,但(inner) join无法强行指定,通常来说都是通过系统自动去判定

强行指定方式:straight_join

这个参数会强行指定左表是外表

例子就截个别人的图吧

多表join优化案例

eg.

红框处是可能需要加索引的各种连接谓词和本地谓词,蓝框标示了执行顺序扫描方式等帮助信息

#对执行计划进行分析

在执行计划的第5行可以发现pcb表走了全表扫描,扫描行数达到95W行;通过执行计划的第4行可以发现这里有一个派生表,这个派生表是由pcb和ppv做inner join形成的,这里很明显pcb成了这个连接查询的外表,查询ppv表,发现ppv表仅仅只有19行。这是典型的大表驱动小表

查询pcb表的索引,发现pcb表的连接谓词和本地谓词上面都没有建索引!而ppv.id是ppv表的主键(mysql优化器大概就是因为这个原因让ppv表做了内表吧...)

把pcb表的连接谓词和本地谓词做了一个联合索引之后,扫描行数从95W缩减至5.4W,优化器很识趣的将ppv选做外表了

消灭了95W行的扫描之后,盘面上最刺眼的就是第二行那个2871了,对pc表的索引进行查询发现pc.client_no列上也没有索引,由于pc.client_no列是一个本地谓词,在添加索引之后,pc表直接跳到了explain的第一行。优化后的执行计划如下图

对比pp表和pc表,pp表有16行数据,pc表有3000行数据,都不算太大,无论谁作为驱动表都不会有太大的性能提升了,优化也到此结束;执行时间由1s缩减到0.29s

参考文章

2.《索引设计与优化》

mysql多张表join_SQL优化之多表join相关推荐

  1. psql where里有自定义函数慢_阿里P8架构师谈:MySQL慢查询优化、索引优化、以及表等优化总结...

    MySQL优化概述 MySQL数据库常见的两个瓶颈是:CPU和I/O的瓶颈. CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候. 磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应 ...

  2. 阿里P7架构师谈:MySQL慢查询优化、索引优化、以及表等优化总结

    MySQL优化概述 MySQL数据库常见的两个瓶颈是:CPU和I/O的瓶颈. CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候. 磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应 ...

  3. 阿里P8架构师谈:MySQL慢查询优化、索引优化、以及表等优化总结

    MySQL优化概述 MySQL数据库常见的两个瓶颈是:CPU和I/O的瓶颈. CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候. 磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应 ...

  4. 阿里对mysql的优化_阿里P8架构师谈:MySQL慢查询优化、索引优化、以及表等优化总结...

    更多内容:https://www.toutiao.com/i6599796228886626829/?tt_from=weixin&utm_campaign=client_share& ...

  5. mysql 多表查询 优化_Mysql 多表联合查询效率分析及优化

    1. 多表连接类型 1. 笛卡尔积(交叉连接)在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用','  如: SELECT * FROM table1 CROSS JOI ...

  6. mysql myisam表_mysql优化之MyISAM表锁

    概述 MyISAM存储引擎只支持表锁,mysql的表锁有两种模式:读锁和写锁. 他们的兼容关系是(对myisam的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写操作*)和(对myisa ...

  7. mysql 多表查询 优化_MySql多表查询优化

    一.多表查询连接的选择 相信内连接,左连接什么的大家都比较熟悉了,当然还有左外连接什么的,基本用不上,我就补贴出来了,这个图只是让大家熟悉一下各种连接查询.然后要告诉大家的是,需要根据查询的信息,想好 ...

  8. MySQL分库分表和优化

    第九阶段模块三 分库分表技术之MyCat 1.海量存储问题 1.1 背景描述 随着互联网的发展,数据的量级也是成指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无 ...

  9. mysql一张表100亿条数据_一个表有100亿条记录,如何优化

    我们的数据库还在设计阶段.我们预计数据量将会很大,一年的时间里,一张表,就会产生100亿条数据,表结构,如下id,userid,createddate,等等正常情况下,100亿条记录如果都存在一个表里 ...

最新文章

  1. android TextView显示文字和图片
  2. 直播预告|中台基石腾讯云TStack的正确使用姿势
  3. 【php7扩展开发五】函数调用
  4. C++远航之封装篇——构造函数
  5. 计组之中央处理器:8、五段式指令流水线
  6. 查看jvm的full gc的频率
  7. 虚拟机、集群、数据中心虚拟化
  8. CF914D Bash and a Tough Math Puzzle 线段树
  9. win10系统 Windows 资源保护找到了损坏文件 无法修复的有效解决方法
  10. 计算机word大作业,计算机操作基础--Word大作业要求.doc
  11. 安卓微博登录第三方详解
  12. RabbitMQ:镜像队列Mirrored queue
  13. 安装与下载 Android studio(以下为处理器是Intel的安装方法,下载前请检查一下自己的CPU为AMD 还是Intel的)
  14. TX2--wifi模块开启AP路由功能
  15. python 编码 乱码问题
  16. windows搭建hadoop环境(解决HADOOP_HOME and hadoop.home.dir are unset)
  17. voice conversion
  18. 【元胞自动机】元胞自动机交通流模拟仿真【含Matlab源码 1252期】
  19. 关于echarts生成地图的二三事
  20. linux交叉编译环境介绍,交叉编译环境介绍

热门文章

  1. 个人站长的出路在哪儿?
  2. java抓取qq消息_Java代码---实现爬取腾讯新闻
  3. 魔术师乔布斯,炼金术士苹果——苹果公司第四季度报表简评
  4. 运用Java制作一个属于自己的音乐播放软件
  5. JMeter压力测试,mongodb教程视频百度云
  6. 珈和卫星遥感助力2021年小麦“两病一虫”防控
  7. 苹果CEO库克: 请无所畏惧,做最不愿接受现状的人丨2018年毕业典礼演讲
  8. 被问懵了,加密后的数据如何进行模糊查询?
  9. mysql经典问题四表查询(教师,学生,成绩,课程表)
  10. 去除人声--安装和使用spleeter分离人声和背景声