SQL优化之多表join

关于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


参考文章

1.MySQL的JOIN

2.《索引设计与优化》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,653评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,321评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,833评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,472评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,306评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,274评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,658评论 3 385
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,335评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,638评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,697评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,454评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,311评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,699评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,986评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,254评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,647评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,847评论 2 335

推荐阅读更多精彩内容