2019独角兽企业重金招聘Python工程师标准>>>

/* *  --------------------------------------------------------            *     高性能MySQL-3rd-Baron Schwartz-笔记             *     第六章 查询性能优化    */  --------------------------------------------------------

======================================================

6.1 为什么查询速度会变慢

查询有生命周期大致顺序:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,返回结果给客户端,其中执行是最重要的阶段。包括了大量的检索数据到存储引擎的调用,调用后的数据处理,分组和排序。

查询在每个部分都会花费时间,包括网络、CPU计算、生成执行计划、锁等待(互斥等待),尤其是向存储引擎调用操作,这些调用需要在内存操作、在CPU操作、内存不足时导致I/O操作。

了解以上就可能知道查询速度会变慢的思考角度。

======================================================

    6.2 慢查询基础:优化数据访问

优化数据访问,就是优化访问的数据,操作对象是要访问的数据,两方面,是否向服务器请求了大量不需要的数据,二是是否逼迫MySQL扫描额外的记录(没有必要扫描)。

请求不需要数据的典型案例:不加LIMIT(返回全部数据,只取10条)、多表关联Select * 返回全部列(多表关联查询时*返回多个表的全部列)、还是Select *(可能写程序方面或代码复用方面有好处,但还要权衡)、重复查询相同数据(真需要这样,可以缓存下来,移动开发这个很有必要本地存储)。

标志额外扫描的三个指标:响应时间(自己判断是否合理值)、扫描的行数、返回的行数,一般扫描行数>返回行数。

扫描的行数需要与一个“访问类型”概念关联,就是 Explain 中的 type,explain的type结果由差到优分别是:ALL(全表扫描)、index(索引扫描)、range(范围扫描)、ref(唯一索引查询 key_col=xx)、const(常数引用)等。从“访问类型”可以明白,索引让 MySQL 以最高效、扫描行数最少的方式找到需要的记录。

书中有个例子,说明在where中使用已是索引的列和取消该列的索引后两种结果,type由ref变为All,预估要访问的rows从10变为5073,差异非常明显。

======================================================

    6.3 重构查询的方式

第一:将一个复杂查询拆分为数个小且简单的查询,数据返回也快。

第二:切分查询,如删除10万条数据,可以切分为10次,每次删除1万条。

第三:分解关联查询:

以上做法好处是,充分利用前一步缓存,减少锁竞争,in(123, 456,...)也更高效,减少冗余记录,等等。

======================================================

    6.4 查询执行的基础(知识)

MySQL执行查询执行路径,如下图,关键要解释的是 客户端发送请求,如果查询缓存有结果,则直接返回。

客户端/服务器通讯协议,具体细节不关注,只知道它是“半双工”工作,要么客户端向服务器发送数据,要么服务器向客户端发送数据,两个动作不会同时发生;另外,发送数据都只有发送完成后才能动作,这就是为什么要加LIMIT。

另外,注意当客户端从服务器获取数据时,看起来是从服务器获取数据,实际上是从库函数的缓存中获取数据,想想PHP的 mysql_query(),此时数据已经到了PHP的缓存中,而mysql_unbuffered_query()不会缓存结果。

MySQL中的关联(join)查询,总体来说,MySQL认为任何一个查询都是一次关联,不光是查询两个表匹配才叫关联。所以,理解MySQL如何执行关联查询至关重要。MySQL的关联是:嵌套循环关联,举例如下:

结合书中关于多表关联的案例,参考一个实际例子 《MySQL SQL优化之 STRAIGHT_JOIN》 全面介绍优化过程。

排序优化,不管怎么样,从性能角度,应该尽可能避免排序,或者尽可能避免对大量数据进行排序。第三章讲了索引排序,快速,当不能直接使用索引时,MySQL就会自己进行排序,数据量小时在内存中排序,数据量大时使用到磁盘。量小于“排序缓冲区”时,MySQL使用内存进行“快速排序”。如果内存不够,MySQL先将数据分块,每块使用快速排序,然后将各块结果放在硬盘上,然后合并(merge),最后返回排序结果。

注意:MySQL排序过程统称为文件排序(filesort),概念上的,即使排序发生在内存,而不是磁盘文件中。

MySQL有两种排序算法,两次传输排序(旧版)、单次传输排序(新版)。两种各有各的最好和最差的应用场景,注意 max_length_for_sort_data 是临界值,不超过时使用单次传输,超过使用两次传输。MySQL自动判断,具体参考第八章中“文件排序优化”。

两次传输排序(旧版),读取行指针和需要排序的字段,对其进行排序,然后再根据排序结果读取所需要的数据行。显然是两次传输,特别是读取排序后的数据时(第二次)大量随机I/O,所以两次传输成本高。

单次传输排序(新版),一次读取出所有需要的或SQL查询指定的列,然后根据排序列,排序,直接返回排序后的结果。顺序I/O,缺点:如果列多,额外占用空间。

注意:MySQL排序时使用的空间比想象大很多,为什么?因为MySQL要为每一个排序记录分配足够长的空间存放,VARCHAR满长度(声明的完整长度),使用UTF8字符集时,为每个字符预留3个字节。所以会很大!

结合关联查询,排序会更复杂。如果ORDER BY排序列都在第一个表(驱动表),那么在关联处理时,先对驱动表排序,Explain结果中Extra会有Using filesort;除此之外所有情况,都会在关联结束后,将结果放在临时表中进行最终排序,Extra中会有Using temporary;Using filesort。如果还有LIMIT,也会在排序后应用。可以,排序需要的空间大!

注意:MySQL5.6以后,有所优化,如果有LIMIT会只排序需要的,而不是所有,抛弃不满足条件的结果。

查询执行引擎,相对于查询优化,查询执行简单些了,MySQL只根据执行计划输出的指令逐步执行。指令都是调用存储引擎的API来完成,一般称为 handler API,实际上,MySQL优化阶段为每个表都创建了一个 handler 实例,(类似于VC++编程中的句柄?),用 handler 实例获取表的信息(列名、索引统计信息等)。

注意:存储引擎接口不丰富,底层仅几十个,但功能丰富!如某接口实现了查询第一行,又有一个接口实现了查询下一行,有了这两个就可以全表扫描了!

返回结果给客户端,有结果集返回结果集,没结果,返回影响的行数。一般MySQL也会将这个结果缓存下来,存放到查询缓存中。

注意:MySQL返回结果是一个增量、逐步返回的过程,例如,关联操作中,当一个嵌套循环处理到最后一个关联表,并开始生成第一条结果时,MySQL就可以开始向客户端逐步返回结果集了。好处:服务器端无须存储太多结果,也不会因为返回的结果太多而消耗太多内存,也使客户端第一时间获得返回结果。结果是以TCP协议封包发送的,TCP的传输过程,可能会对封包进行缓存然后批量发送。

======================================================

    6.5 MySQL查询优化器的局限性

不熟悉 JOIN USING 和 JOIN ON 的请看 红薯作品 MySQL 三种关联查询的方式: ON vs USING vs 传统风格

一个是关联子查询,没看明白,回来再读。

一个UNION限制,无法将限制条件从外层下推到内层,改造例子如下

等值传递:讲的IN列表,MySQL会将IN列表的值传到各个过滤子句,如果IN列表太大,会造成额外消耗,优化和执行都很慢。

并行执行,MySQL无法执行并行查询,不用白费力气了。

哈希关联,MySQL不支持哈希关联,所有关联都是嵌套循环关联。

松散索引扫描,MySQL不支持松散(跳跃),仍需要扫描每一个条目。

最大值和最小值,MySQL对 MIN()和MAX()做得不好。看一个例子,强制使用索引来优化(use index(xx))。

在同一个表上查询和更新,MySQL不允许这样。

======================================================

6.6 查询优化器的提示(hint)

讲到了很多提示,意在如果我们对优化器选择的执行计划不满意,使用提示来控制最终的执行计划,如上面的 USE INDEX(PRIMARY),其他还有:HIGH_PRIORITY、LOW_PRIORITY、DELAYED、STRAIGHT_JOIN(上文提到过)、SQL_SMALL_RESULT、SQL_BIG_RESULT、SQL_BUFFER_RESULT、SQL_CACHE、SQL_NO_CACHE、SQL_CALC_FOUND_ROWS、FOR UPDATE、LOCK IN SHARE MODE、USE INDEX、IGNORE INDEX、FORCE INDEX等等。

======================================================

    6.7 优化特定类型的查询

6.7.1 优化 COUNT()查询

COUNT()常被误解(难道这本书里说的对的?),COUNT()有两个作用,1、统计非NULL列的列植的数量,2、统计返回数据集的行数;常用的是COUNT(*),*常被误解为所有列,实际上在操作时是忽略所有列,而直接统计所有行数。COUNT(*)中的*与SELECT *中的*是不同的。如果你真想统计结果集的行数,就用 COUNT(*)而不要使用 COUNT(aCol)。

通常以为 MyISAM执行COUNT(*)最快,实际上是有条件的,只有不用 WHERE时,因为MySQL根本不用扫描数据行,也无须去计算,会直接利用存储引擎的特性去获得这个值。当带上 WHERE 上,就需要去扫描去计算了。

书中一个优化的例子,将条件反转后可大大加速,如查询 id > 5 的数量有4097行,而反转,查询 id < 5 的,只有几行,然后 用总行数(用 COUNT(*) 获取-常数不费计算)减去 id < 5的,大大优化。但这种情况貌似我提前可以知道 id > 5的数据比 id < 5 的数据多很多才可以。

能使用近似值的就不必追求精确计算值,代价太高!

6.7.2 优化关联查询

这个话题基本整本书都在讨论(还是很晕),注意一下:

1)确保ON或USING子句中的列上有索引,在创建索引时就要考虑到关联的顺序。

转载于:https://my.oschina.net/zhmsong/blog/194326

高性能MySQL-3rd-(六)查询性能优化相关推荐

  1. 读薄《高性能MySql》(四)查询性能优化

    读薄<高性能MySql>(一)MySql基本知识 读薄<高性能MySql>(二)Scheme与数据优化 读薄<高性能MySql>(三)索引优化 读薄<高性能M ...

  2. 高性能MySQL学习——提高查询性能

    高性能MySQL学习--提高查询性能 提高查询性能 MySQL 查询优化器 MySQL 执行计划分析"三步曲" MySQL 执行计划查询分析 如何优化 SQL MySQL 自身优化 ...

  3. mysql笔记03 查询性能优化

    查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...

  4. MySQL系列-- 4. 查询性能优化

    4. 查询性能优化 4.1 为什么查询速度会变慢 快速查询取决于响应时间 如果把查询看成是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消 ...

  5. mysql分页 disti_MySql查询性能优化

    慢查询判定 1.开启慢查询日志记录执行时间超过long_query_time 秒的sql语句 2.通过show processlist命令查看线程执行状态 3.通过explain解析sql了解执行状态 ...

  6. 【MVC+MySQL+EntityFramework】查询性能优化笔记

    通过在DbContext中定了表之间的关系,查询后在View中通过item.ProjectOverHour来显示关联表数据. modelBuilder.Entity<ProjectOverHou ...

  7. MySQL查询性能优化七种武器之索引下推

    前面已经讲了MySQL的其他查询性能优化方式,没看过可以去了解一下: MySQL查询性能优化七种武器之索引潜水 MySQL查询性能优化七种武器之链路追踪 今天要讲的是MySQL的另一种查询性能优化方式 ...

  8. 高性能Mysql之查询性能优化

    高性能Mysql之查询性能优化 为什么查询速度会慢 慢查询基础:优化数据访问 重构查询的方式 MySQL查询优化器的局限性 优化特定类型的查询 即使我们设计了一个最优的库表结构,建好了最好的索引,如果 ...

  9. mysql获取查询策略语句_MySQL数据库查询性能优化策略

    优化查询 使用Explain语句分析查询语句 Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句. 通过对查询语句的分析,可以了解查询语句的执行 ...

最新文章

  1. jasp报错_JSP报错!成功解决问题200+追加分数!
  2. 2、cookie session token详解
  3. 纯C写Windows程序系列---------VS2010设置纯C环境 .
  4. 搜索长度未知的有序数组java_java二分法实现在有序的数组中定位某数在数组中的位置...
  5. java一行交换,在C / C ++,Python,PHP和Java中一行交换两个变量
  6. 苹果6软件服务器验证失败是怎么回事,iPhone6手机出现验证错误怎么办?
  7. React学习笔记—表单
  8. 凸优化有关的数值线性代数知识二:求解已经因式分解的矩阵的线性方程组
  9. 西门子S7系列中间人攻击:PLC探测和流量分析(二)
  10. AJAX 简单例程示例
  11. Hive On Spark搭建报错:Failed to create Spark client for Spark session xx: ..TimeoutException
  12. 计算机平板传输软件,如何在iPad和电脑之间无线传输文件
  13. 2022年全球与中国一次性内窥镜市场现状及未来发展趋势
  14. 2021-2027全球与中国电动汽车PTC加热器市场现状及未来发展趋势
  15. 戴尔笔记本一键重装win7系统教程
  16. mysql server安装及配置
  17. 【项目--Hi3559A】Hi3559A平台仿真功能操作介绍
  18. 计算机平面设计师外部环境,职业生涯规划书之平面设计师_图文.doc
  19. ubuntu15.04 + ROS jade
  20. Dundas Chart Demo For New User

热门文章

  1. html 新append后的元素如何注册click
  2. MyBatis学习与使用(一)
  3. Spring Cloud基础教程
  4. 页面按钮埋点+跟踪location.search
  5. MYSQL优化---hidba
  6. 《文献管理与信息分析》课程学习笔记
  7. Delphi RTC
  8. 我想在 2012 储备的技术
  9. 关于C语言的一些小知识点
  10. Git常用命令备忘(一) 转载