查询优化详解

查询优化

参考:https://www.cnblogs.com/Courage129/p/14199151.html

一、优化器的优化策略

静态优化
直接对解析树进行分析,并完成优化

动态优化
动态优化与查询的上下文有关,也可能跟取值、索引对应的行数有关

二、Mysql能够处理的优化类型:

1、重定义关联表的顺序: 数据表的关联并不总是按照在查询中指定的顺序进行,决定关联顺序时优化器很重要的功能

2、将外连接转换成内连接,内连接的效率要高于外连接

3、使用等价变换规则,mysql可以使用一些等价变化来简化并规划表达式

4、优化count()、max()和min()
索引和列是否可以为空通常可以帮助mysql优化这类表达式:例如,要找到某一列的最小值,只需要查询索引的最左端的记录即可,不需要全文扫描比较

5、预估并转化为常数表达式,当mysql检测到一个表达式可以转化为常数的时候,就会一直把该表达式作为常数进行处理

explain select film.film_id,film_actor.actor_id from film inner join film_actor using(film_id) where film.film_id = 1

6、覆盖索引扫描, 当索引中的列包含所有查询中需要使用的列的时候,可以使用覆盖索引

7、子查询优化
mysql在某些情况下可以将子查询转换一种效率更高的形式,从而减少多个查询多次对数据进行访问,例如将经常查询的数据放入到缓存中

8、等值传播

如果两个列的值通过等式关联,那么mysql能够把其中一个列的where条件传递到另一个上:

explain select film.film_id from film inner join film_actor using(film_id

) where film.film_id > 500;
这里使用film_id字段进行等值关联,film_id这个列不仅适用于film表而且适用于film_actor表

explain select film.film_id from film inner join film_actor using(film_id

) where film.film_id > 500 and film_actor.film_id > 500;

9、提前终止查询

10、列表in()的比较

三、关联查询

mysql的关联查询很重要,但其实关联查询执行的策略比较简单:mysql对任何关联都执行嵌套循环关联操作,即mysql先在一张表中循环取出单条数据,然后再嵌套到下一个表中寻找匹配的行,依次下去,直到找到所有表中匹配的行为止。然后根据各个表匹配的行,返回查询中需要的各个列。mysql会尝试再最后一个关联表中找到所有匹配的行,如果最后一个关联表无法找到更多的行之后,mysql返回到上一层次关联表,看是否能够找到更多的匹配记录,以此类推迭代执行。整体的思路如此,但是要注意实际的执行过程中有多个变种形式.

join的实现方式原理

simple Nested-Loop Join:

===> 左边的r 为驱动表,右边的s 为匹配表,可以看到从 r 中分别取出每一条记录去匹配 s 表的列,然后在合并数据, 对 s 表进行 r 表的行数次访问,对数据库的开销比较大。

Index Nested-Loop Join:

====> 这个要求非驱动表(匹配表 s) 上有索引,可以通过索引来减少比较,加速查询。

  在查询时,驱动表(r)会根据关联字段的索引进行查找,当在索引上找到符合的值,再回表进行查询,也就是只有当匹配到索引以后才会进行回表查询。

  如果非驱动表(s)的关联健是主键的话,性能会非常高,如果不是主键,要进行多次回表查询,先关联索引,然后根据二级索引的主键ID进行回表操作,性能上比索引是主键要慢。

Block Nested-Loop Join:

====> 如果有索引,会选取第二种方式进行join,但是如果join列没有索引,就会采用Block Nested-Loop Join。
可以看到中间有个join buffer中,然后批量与匹配表进行匹配,将第一种多次比较合并为一次,降低了非驱动表(s)的访问频率。默认情况下join_buffer_size = 256k,在查询的时候

  Mysql 会将所有的需要的列缓存到join buffer 当中,包括select的列, 而不是仅仅只缓存关联列。在一个有N个JOIN关联的SQL 当中会在执行的时候分配 N-1 个join buffer。

算子与列的关系:

Selection(Where 条件)、Projection(搜索的列)、Sort(排序列)、Join(等值连接)、Aggregation(Group By及相关聚合操作)

列裁剪:
列裁剪的算法就是自顶向下的把算子过一遍,某个节点需要用到的列就等于它自己需要用到的列加上它的父节点所需要用到的列。这样得到整个SQL语句所涉及到的列,从而再读取数据时只读取需要的列即可。

谓词下推(含join优化) 参考:https://www.cnblogs.com/Courage129/p/14175363.html

在SQL中,谓词就是返回boolean值即true或者false的函数,或是隐式转换为boolean的函数。SQL中的谓词主要有 LKIE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS

==> where 谓词下推场景:

对于查询:select * from t1 left join t2 on t1.id = t2.cid where t2.cname="kingsoft";

在SQL中,将where后面的条件下推;

谓词条件 inner join left join right join full join
left table right table left table right table left table right table left table right table
where predicate √ √ √ × × √ × ×

没有下推,在join后过滤,下推之后,在join前过滤。由于Join本身具有补null的逻辑,会导致最终数据错误。

==> join谓词下推场景:

对于查询:select * from t1 left join t2 on t1.id = t2.cid and t1.name="kingsoft";

在SQL中,将join的条件下推:

谓词条件 inner join left join right join full join
left table right table left table right table left table right table left table right table
join predicate √ √ x √ √ × × ×

/*************************************/
总结起来,关于join和where采用ppd 的规则如下:

谓词条件 inner join left join right join full join
left table right table left table right table left table right table left table right table
where predicate √ √ √ × × √ × ×

join predicate √ √ x √ √ × × ×

1、对于Join(Inner Join)、Full outer Join,条件写在on后面,还是where后面,性能上面没有区别;

2、对于Left outer Join ,右侧的表写在on后面、左侧的表写在where后面,性能上有提高;

3、对于Right outer Join,左侧的表写在on后面、右侧的表写在where后面,性能上有提高;

4、所谓下推,即谓词过滤在map端执行;所谓不下推,即谓词过滤在reduce端执行

注意:如果在表达式中含有不确定函数,整个表达式的谓词将不会被pushed,例如

select a.* from a join b on a.id = b.idwhere a.ds = '2019-10-09' and a.create_time = unix_timestamp();
因为unix_timestamp是不确定函数,在编译的时候无法得知,所以,整个表达式不会被pushed,即ds='2019-10-09'也不会被提前过滤。类似的不确定函数还有rand()等。

/*************************************/

====> 外链接优化

外连接的特点是返回的结果集只会包含外表的所有行,如果外表的某行通过连接列内表没有能够匹配的行,则在结果集的右边补NULL。

如果连接后的where谓词条件能够将包含NULL的行全部过滤,那么此外连接的结果集将等价于内连接,即可将此外连接查询改写为内连接。

综上,当where谓词条件能够满足以下三种能够过滤NULL条件的任意一种时,可进行外连接优化:

  1. 某个谓词的表达式用NULL值计算后会得到False或NULL。

select * from t1 left outer join t2 on t1.id = t2.id where t2.id is not null;

select * from t1 left outer join t2 on t1.id = t2.id where t2.value > 3;

  1. 多个谓词用AND连接,其中一个能够过滤NULL。

select * from t1 left outer join t2 on t1.id = t2.id where t2.value > 3 and t2.id is null;

  1. 多个谓词用OR连接,每一个都能够过滤NULL。

select * from t1 left outer join t2 on t1.id = t2.id where t2.id is not null or t2.value > 3;

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

推荐阅读更多精彩内容

  • 一、MapReduce完整流程 MapTask工作机制 ReduceTask工作机制 MapTask工作机制: (...
    扎西的德勒阅读 950评论 0 0
  • 1 安装MySQL 进入MySQL官网,登录 如何在Macbook上安装MySQL_百度经验 我之后改了个,怕忘记...
    乔大叶_803e阅读 489评论 0 0
  • 1. 摘要 MySQL用来加快查询的技术很多,其中最重要的是索引。通常索引能够快速提高查询速度。如果不适用索引,M...
    笔名辉哥阅读 1,884评论 1 17
  • 前言 本文将结合实例demo,阐述30条有关于优化SQL的建议,多数是实际开发中总结出来的,希望对大家有帮助。 1...
    Minnakey阅读 369评论 0 1
  • MYSQL 基础知识 1 MySQL数据库概要 2 简单MySQL环境 3 数据的存储和获取 4 MySQL基本操...
    Kingtester阅读 7,790评论 5 116