6.5查询优化器的局限性

mysql优化器是有局限性的,有时需要我们改写查询以提高效率。

6.5.1关联子查询

子查询是mysql一个很不效率的地方。

这一节首先我们需要了解一下相关子查询:内外部查询间有一个关联条件,类似于join中的等值条件

书中说尽量不要使用in来写相关子查询。推荐使用exists与join的方式来替代。

我感到比较迷惑

书中说mysql优化器会将用in非关联子查询解析为exists关联子查询。那么用exists优化in有什么意义呢?

我做的两个测试中exists与in的explain结果是一致的?

Exists与in的不同通过英文的简单理解就可以明白,exists是存在,返回一个bool值,只要

子查询查到有一个值成立就立马返回,能减少子查询的消耗。

关联子查询的效率是很低的,每一条外部查询的数据行都要让内部查询执行一次。而关联查询join则是一次性将n*m的结果全部罗列,还能通过where条件筛选,更容易优化。(自己的理解)

如何用好关联子查询

子查询并不一定是效率不好的,在合适的时候它也可以使用。具体情况应该explain以后再看结果。

6.5.2union的限制

一些情况union无法将where条件下推到内层,例如分语句的limit20。Union的分语句不可能有超过20条被留下,limit20应该是可以下推的,我们需要手动说明。

这里要注意从临时表去除数据顺序是不固定的。

6.5.3索引合并优化

5.0以后索引已经可以通过索引合并和交叉过滤的方式来定位目标行。

类型列中显示为index_merge

6.5.4等值传递

在关联中对于关联条件的筛选可以下推到各个子查询中。

6.5.5并行执行

Mysql无法利用多核特性并行查询。

6.5.6哈希关联

Mysql不支持哈希关联,不过可以通过自实现的哈希索引来实现哈希关联。

6.5.7松散索引扫描

Mysql不支持松散索引扫描。5.0后在某些条件下可以实现松散索引扫描

Extra列显示 using index for group-by

6.5.8最大值最小值优化

Mysql并不能使用索引的来获取极值,即使索引是有序的,他依然进行全表扫描。有时候我们可以用limit加上指定索引来手动指定返回摸个索引的第一行或者前几行。这个问题myisam解决的不错啊。

6.5.9在同一个表上查询和更新

Mysql不允许在同一张表中同时进行查询与更新。

可以注意奥上文中关联子查询是需要两条查询进行嵌套的,当这两条sql一条为更新,一条为查询是就会报错。这时可以采用关联子查询一节中的处理方式将其转换为join查询的。

6.6查询优化器提示(hint)

这一节给出了dba控制sql的执行计划的方式,即hint。这里我不在罗列hint。在使用hint时要通过详细的测试hint是否能带来效率的提升。(delayed, straight_join, use index ,force index, ignore index)

6.7优化特定类型的查询

6.7.1优化count()

Mysql的count()是不统计空值的。只有才确定一行一定不为空的情况下才能统计行数。

Myisam的count()并不总是非常高效的只有没有where时myisam才能将存储的count(col)

值优化为count(*)才能高效的实现count(*)

简单的count优化

在myisam中我们知晓count(col)的代价很小,但我们需要一个count where 的数据时,可以在合适情况下采用总数减去不需要的行数的办法获取count。

使用近似值

这一类的代表为innodb这样的引擎,即通过explain执行计划来估算查询的行数。

跟复杂的优化

可以使用汇总表来记录时常要用到的统计值来优化。

6.7.2优化关联查询

  1. 关联字段有索引很重要的,但是只有内部查询需要索引,因为外部查询是用不到该列的索引的。
  2. 确保任何的group by与order by只涉及一个表中的列,这样mysql才能使用索引来优化这个过程。
  3. Mysql版本的升级可能会影响关联查询的执行方式

6.7.3优化子查询

尽量使用关联查询(醉了前面说那么多子查询还行后面还是让你用关联查询)

6.7.4优化group by和order by

Group by默认会按照分组字段进行排序,如果不需要排序,可以使用 order by NULL 来禁止排序。需要特定顺序也可以使用desc,asc。

Group by 语句中不于分组字段直接关联的都是无意义的返回值,不同的环境,可能有不同的非关联返回值。

Group by with rollup

超级聚合,可以将分组的结果进行一次超级聚合,即聚合后的总计。在分组项有多项式会有更多的组合。不过Group by with rollup 并不是处理此类需求的一个号的解决方式,最好还是通过程序来解决。

6.7.5优化limit分页

Limit能够减少返回的结果集,所以尽可能早的使用order by与limit能有效减少io次数。

对于offset(取数据的起始值)关键字,我们应该尽量不使用,可以用自定义书签的方式,来访问偏后的数据,但是这样往往需要数据字段中有一个可以预估增长方式的值。

6.7.6优化sql_calc_found_rows

这个hint要求sql扫描所有满足where条件的行,再根据limit抛弃不需要的行。这样的需求往往是我们需要提供一个总的记录数才需要给出该hint,

6.7.7优化union查询

一句话用union all而不用union。

使用union会给要求加入结果集的数据唯一,而对所有数据行进行唯一性检查,这样额外的开销。     当然跟好的做法是不使用union而将各个查询的结果返回给客户端,让客户端来实现union(union的结果集会保存在一个临时表中,返回给客户端有需要将临时表中的数据读取出来)。

6.7.8静态查询分析

通过工具为所有的查询语句做一个体检。

6.7.9使用用户自定义变量

使用用户自定义变量可以保存一些查询结果,用来在sql中实现应用程序中的逻辑而不是通过关联查询等等方式来体现逻辑。是一种解决方式,不过在存储过程中使用的比较多。

  1. 优化排名语句

自定义变量可以作为左值(可以赋值)。

可以通过自定义变量来自实现类似count的功能,甚至可以对’count’的过程加上条件!来实现排名功能!(具体事例书中查看)

  1. 避免重复查询刚刚插入的数据

标题很迷惑人,其实就是但你需要将你刚刚插入的数据返回时!Mysql没有相应的语法来一次性实现这样的功能(postgreSQL提供update return语法)。我们必须使用一条insert以及一条select两条语句来实现。

而使用变量保存我们刚刚跟新的值的就可以免于select语句的执行。

  1. 统计更新与插入数量

在Insert on duplicate key update 可以计算update的记录数,通过mysql返回的总行数可以知道insert的记录数。(Insert on duplicate key updatec1=values(c1)+0*(@x:=@x+1))

  1. 确认取值的顺序

但语句使用到using temporary与using filesort时可能会导致变量的值。可以通过一个字符处理函数将变量赋值包括进去。例如least()。

  1. 编写偷懒的union

可以通过一个变量的使用来避免第一个union分支已经找到数据的情况下,后续分支依然要执行的情况。

  1. 用户自定义变量的其他用处

总结:起来就是查询进行中的自定义单条数据判断条件控制。

6.8案例学习

6.8.1使用mysql构建一个对列表

  1. 应该尽量避免select for update,而应该使用在sql中connection_id()来判断有没有用户正在访问这条记录。
  2. 如果逻辑允许一个事务中应该先update再select会更好。

6.8.2计算两点间的距离

这个例子告诉我们。

  1. 少做事,用尽量少的逻辑来实现功能。(指的是少用sql实现)
  2. 能否使用索引会严重影响查询的效率,不过也不是无脑索引
  3. 尽可能的让应用程序来完成计算的部分。

体会:

第六章的内容其实就是介绍了sql的优化,以及我们在配合程序编写sql时应该注意什么?

在几个月的工作中,发现sql部分优化往往都不是前期开发的关键,因为,应用程序的处理会让我们比较轻易的将一整条sql拆分成多条简单的sql,在配合合适的索引,sql往往都不会有太大的问题。。但是也许程序发布以后流量打起来sql的问题就来了

mysql高性能6章总结(下) mysql查询优化的更多相关文章

  1. Mysql优化系列--Innodb引擎下mysql自身配置优化-转

    原文链接:http://www.cnblogs.com/kevingrace/p/6133818.html 谢谢楼主 1.简单介绍 InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全 ...

  2. MySQL高性能优化系列-目录

    MySQL高性能优化系列-目录 (1)Mysql高性能优化规范建议 (2)电商数据库表设计 (3)MySQL分区表使用方法 (4)MySQL执行计划分析 (5)电商场景下的常见业务SQL处理 (6)M ...

  3. linux下mysql的卸载、安装全过程

    卸载mysql 1.查找以前是否装有mysql 命令:rpm -qa|grep -i mysql 可以看到mysql的两个包: mysql-4.1.12-3.RHEL4.1 mysqlclient10 ...

  4. [转]Ubuntu10下MySQL搭建Amoeba系列(文章索引)

    一.前言(Introduction) 使用了Amoeba有一段时间了,发现官方博客:Amoeba使用指南有很多地方都是错误的,在我实战中给到一些错误的指示,所以我想写些在搭建的实战中给大家一点指引.欢 ...

  5. Windows环境下Mysql如何快速导入或恢复表为innodb的数据

    注: 一.这个是对Innodb的数据恢复.MyISAM不需要这么麻烦,只要数据文件存在直接复制过去就可以. 二.该方法只适用于 1:想要恢复或者导入表的ibd文件和frm文件 2:你不仅需有ibd和f ...

  6. (转)Windows下MySQL :GUI安装和使用(MySQL GUI tools)

    原文:http://blog.csdn.net/dahunbi/article/details/52970815 MySQL GUI Tools是MySQL官方提供的图形化管理工具,功能很强大,值得推 ...

  7. Linux下MySQL/MariaDB Galera集群搭建过程【转】

    MariaDB介绍 MariaDB是开源社区维护的一个MySQL分支,由MySQL的创始人Michael Widenius主导开发,采用GPL授权许可证. MariaDB的目的是完全兼容MySQL,包 ...

  8. 数据库:ubantu下MySQL安装指南

    http://wiki.ubuntu.org.cn/MySQL%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97 安装MySQL sudo apt-get install mys ...

  9. windowns环境下mysql 安装教程

    windowns环境下mysql 安装教程 一:这里以绿色版安装为例(解压就可以使用) 下载地址: 下载页面:https://dev.mysql.com/downloads/mysql/  2:点击 ...

随机推荐

  1. 一天一点Zynq(1)xilinx-arm-linux交叉编译链 安装总结以及资源更新

    结束了对xilinx-arm-linux交叉编译链安装后,总结一下整个过程,方便后来的研究者们,少走点弯路. 关于xilinx-arm-linux交叉编译链的安装,网上一搜一大把,可是有的资料中的资源 ...

  2. 跨域iframe如何通信

    1. 使用document.domain设置相同主域(同主域不同子域): 2. 使用window.name添加空网页: 3. 使用postmessage监听:

  3. python 爬虫 记录

    python3 爬虫需要安装:requests,beautifulsoup4,html5lib 带有中文的需要这样写,要不然就会出现乱码 html = response.content.decode( ...

  4. Python装饰器基础及运行时间

    一.装饰器基础 装饰器是可调用的对象,其参数是另一个函数(被装饰的函数).装饰器可能会处理被装饰的函数,然后把他返回,或者将其替换成另一个函数或可调用对象. eg:decorate装饰器 @decor ...

  5. ef core code frist

    https://docs.microsoft.com/zh-cn/ef/core/get-started/aspnetcore/new-db?view=aspnetcore-2.1 1.先创建对应的实 ...

  6. 截取URL链接中字段的方法

    第一个页面像第二个页面传参方法 location.href = "poster.html?" + "name=" + name + "&tim ...

  7. react 调用webIm

    记录下遇到的问题,之前引用腾讯云的webim,一直出错,现在改好了, 引用了, 以上是在public下的index.html引用, 但是在子模块console.log(webim);会报这个错 解决也 ...

  8. 学习animejs

    1.安装方式 (1)npm install animejs 2.引入 import anime from 'animejs' 3.使用 (anime({ targets: 'div', transla ...

  9. FreeSWITCH与FreeSWITCH对接

    (主机A ---> 主机B)192.168.100.A主机:修改/usr/local/freeswitch/conf/dialplan/default.xml 10         <ex ...

  10. 基于sklearn和keras的数据切分与交叉验证

    在训练深度学习模型的时候,通常将数据集切分为训练集和验证集.Keras提供了两种评估模型性能的方法: 使用自动切分的验证集 使用手动切分的验证集 一.自动切分 在Keras中,可以从数据集中切分出一部 ...