高性能MySQL笔记 第6章 查询性能优化
- 确认应用程序是否在检索大量超过需要的数据。这通常意味着访问了太多的行或列。
- 确认MySQL服务器层是否在分析大量超过需要的数据行。
- 解决方式是在这样的查询后面加上LIMIT
- 解决方式是在列前加上表名
- 通常情况下禁用SELECT *
- 当初次查询的时候将这个数据缓存起来,需要的时候从缓存中取出,这样性能更好
- 响应时间;
- 扫描的行数;
- 返回的行数;
ALL | 全表扫描,通常意味着MySQL必须扫描整张表。(例外,如果查询中使用了LIMIT,Extra列种会显示"Using distinct/not exists") |
index | 与全表扫描一样,只是MySQL扫描表时按索引次序进行而不是行。主要优点是避免了排序,最大的缺点是要承担按索引读取整个表的开销。这通常意味着若是按随即次序访问行,开销将会非常大。 |
range | 范围扫描就是一个有限制的索引扫描,它开始于索引里的某一点,返回匹配这个值域的行。这比全索引扫描好一些,因为他用不着遍历全部索引,显而易见的范围扫描时带有between或在where子句里带有>的查询 |
ref | 这是一种索引访问(有时也叫做索引查找),他返回所有匹配某个单个值得行。然而,他可能会找到多个符合条件的行,因此,它是查找和扫描的混合体。此类索引访问只有当使用非唯一性索引或者唯一性索引的非唯一性前缀时才会发生。把它叫做ref是因为索引要跟某个参考值相比较。这个参考值或者是一个常数,或者是来自多表查询钱一个表的结果值。 |
eq_ref | 使用这种索引查找,MySQL知道最多只返回一条符合条件的记录。这个访问方法可以在MySQL使用主键或者唯一性索引查找时看到,它会将她们与某个参考值做比较。MySQL对于这类访问类型的优化做得非常好,因为他知道无须估计批评行的范围活在找到匹配行后再继续查找。 |
const/system | 当MySQL能对查询的某部分进行优化并将其转换成一个常量时,它就会使用这个访问类型。 |
NULL | 这种访问方式意味着MySQL能在优化阶段分解查询语句,在执行阶段甚至用不着再访问表或者索引。 |
- 在索引中使用where条件来过滤不匹配的记录。这是在存储引擎层完成的。
- 使用索引覆盖扫描(在Extra列中出现Using index)来返回记录,直接从索引中过滤不需要的记录并返回命中的结果。这是在MySQL服务器层完成的,但无须在回表查询记录。
- 从数据表中返回数据,然后过滤不满足条件的记录(在Extra列中出现Using where)。这在MySQL服务器层完成,MySQL需要先从数据表读出记录然后过滤。
- 使用索引覆盖扫描,把所有需要用的列都放在索引中,这样存储引擎无须回表获取对应行就可以返回结果。
- 改变库表结构。
- 重写这个复杂的查询,让MySQL优化器能够以更优化的方式执行这个查询。
- 让缓存的效率更高。许多应用程序可以方便地缓存单表查询对应的结果对象。另外,对MySQL的查询缓存来说,如果关联中的某个表发生了变化,那么久无法使用查询缓存了。而拆分后,如果某个表很少改变,那么基于改表的查询就可以重复利用查询缓存结果了。
- 将查询分解后,执行单个查询可以减少锁的竞争。
- 在应用层做关联,可以更容易对数据库进行拆分,更容易做到高性能和可扩展。
- 查询本身效率也可能会有所提升。
- 可以减少冗余记录的查询。在应用层做关联查询,意味着对于某条记录应用只需要查询一次,而在数据库中做关联查询,则可能需要重复地访问一部分数据。这样的重构还可能会减少网络和内存的消耗。
- 这样做相当于在应用中实现了哈希关联,而不是使用MySQL的嵌套循环关联。某些场景哈希关联的效率要高很多。
- 客户端发送一条查询给服务器;
- 服务器先检查查询缓存,如果命中缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;
- 服务器端进行SQL解析、预处理、再由优化器生成对应的执行计划;
- MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;
- 将结果返回给客户端;
- Sleep:线程正在等待客户端发送新的请求。
- Query:线程正在执行查询或者正在将结果发送给客户端。
- Locked:在MySQL服务器曾,该线程正在等待表锁。在存储引擎级别实现的锁,例如InnoDB的行锁,并不会提现在线程状态中。对于M有ISAM来说这是一个比较典型的状态。
- Analyzing and statistics: 线程正在收集存储引擎的统计信息,并生成查询执行计划。
- Copying to tmp table [on disk]:线程正在执行查询,并且将其结果集都复制到一个临时表中,这种状态一般要么是在做group by操作,是文件排序操作,或者是union操作。如果这个状态后面还有on disk标记,则表示MySQL正在将一个内存临时表放在磁盘上。
- Sorting result:线程正在对结果集进行排序。
- Sending data:线程可能在多个状态之间传送数据,或者在生成结果集,或者在向客户端返回数据。
- 统计信息不准确。MySQL依赖存储引擎提供的统计信息来评估成本,但是有的存储引擎提供的信息是准确的,有的变差可能非常大。
- 执行计划中的成本估算不等同实际执行的成本。所以即使统计信息精确,优化器给出的执行计划也可能不是最优的。
- MySQL只是基于其成本模型下载最优的执行计划,而有些时候这并不是最快的执行方式,
- MySQL从不考虑其他并发执行的查询,这可能会影响到当前查询的速度。
- MySQL也并不是任何时候都是基于成本的优化。有时也会基于一些固定的规则。
- MySQL不会考虑不受其控制的操作的成本,例如执行存储过程或者用户自定义函数的成本。
- 优化器有时无法估算所有可能的执行计划,所以它可能错过实际上最优的执行计划。
- 重新定义关联表的顺序。数据表的关联并不总是按照在查询中指定的顺序进行。
- 将外连接转化成内连接。并不是所有的outer join语句都必须以外连接的方式执行。诸多因素,例如where条件、库表结果都可能会让外连接等价于一个内连接。MySQL能够识别这点并重写查询,让其可以调整关联顺序。
- 使用等价变换规则。MySQL可以使用一些等价变化来简化并规范表达式。它可以合并和减少一些比较,还可以移除一些恒成立和一些恒不成立的判断。
- 优化COUNT()、MIN()、MAX()。索引和列是否可为空通常可以帮助MySQL优化这类表达式。例如,要找到某一列的最小值,只需要查询对应B-Tree索引最左端的记录,MySQL剋直接获取所有的第一行记录。在优化器生成执行计划的时候就可以利用这一点,在B-Tree索引中,优化器会将这个表达式作为一个常数对待。如果MySQL使用了这种类型的优化,那么在EXPLAIN中就可以看到"Select tables optimized away",它表示优化器已经从执行计划中移除了该表,并以一个常数取而代之。
- 预估并转化为常量表达式。当MySQL检测到一个表达式可以转化为常数的时候,就会一直把该表达式作为常数进行优化处理。
- 覆盖索引扫描。当索引中的列包含所有查询中需要使用的列的时候,MySQL就可以使用索引返回需要的数据,而无须查询对应的数据行。
- 子查询优化。MySQL在某些情况下可以将子查询转换成一种效率更高的形式,从而减少多个查询多次对数据进行访问。
- 提前终止查询。在发现已经满足查询需求的时候,MySQL总是能够立即终止查询。例如查询中包含LIMIT子句,或者where条件不成立,这时MySQL可以立即返回一个空结果。
- 等值传播。如果两个列的值通过等式关联,那么MySQL能够把其中一个列的where条件传递到另一列上。
- 列表IN()的比较。在很多数据库系统中,IN()完全等同于多个OR条件的子句,因为这两个是完全等价的。在MySQL中这点事不成立的,MySQL将IN()列表中的数据线进行排序,然后通过二分查找的方式来确定列表中的值是否满足条件,这是一个o(log n)复杂度的操作,等家底转化成OR查询的复杂度为O(n),对于IN()列表中有大量取值的时候,MySQL的处理速度将会更快。
- HIGH_PRIORITY 和 LOW_PRIORITY:控制MySQL访问某个数据表的队列顺序,仅对使用表锁的存储引擎有效。不支持InnoDB。
- DELAYED:这个提示对insert和replace有效。MySQL会将使用该提示的语句立即返回给客户端,比ing将插入的行数据放入到缓存区,然后再表空闲时批量将数据写入。日志系统使用这样的提示非常有效,或者是其他需要写入大量数据但是客户端却不需要等待单条语句完成IO的应用。不支持InnoDB。
- STRAIGHT_JOIN:这个提示可以放置在select语句的select关键字之后,也可以放置在任何两个关联表的名字之间。第一个用法是让查询中的所有的表按照在语句中出现的顺序进行关联。第二个用法则固定其前后两个表的关联顺序。
- SQL_SMALL_RESULT 和 SQL_BIG_RESULT:这两个提示只对select语句有效。他们告诉优化器对group by或者distinct查询如何使用临时表及排序。SQL_SMALL_RESULT告诉优化器结果集会很小,可以将结果放在内存中的索引临时表,以避免排序操作。SQL_BIG_RESULT则告诉优化器结果集可能会非常大,建议使用磁盘临时表做排序操作。
- SQL_BUFFER_RESULT:这个提示告诉优化器将查询结果放入到一个临时表,然后尽可能快地释放表锁。代价是需要更多的内存。
- SQL_CACHE 和 SQL_NO_CACHE:这个提示告诉MySQL这个结果集是否应该缓存在查询缓存中。
- SQL_CALC_FOUND_ROWS:它会让MySQL返回的结果集包含更多的信息。查询中加上该提示MySQL会计算出去LIMIT子句后这个查询要返回的结果集的总数,而实际上只返回limit要求的结果集。
- FOR UPDATE 和 LOCK IN SHARE MODE:控制select语句的锁机制。
- USE INDEX、IGNORE INDEX 和 FORCE INDEX:告诉优化器使用或者不使用哪些索引来查询记录。
- 确保ON或者USING子句中的列上有索引。在创建索引的时候就要考虑到关联的顺序。
- 确保任何的GROUP BY和ORDER BY中的表达式只涉及到一个表中的列,这样MySQL才有可能使用索引来优化这个过程。
- 使用自定义变量的查询,无法使用查询缓存。
- 不能再使用常量或者标识符的地方使用自定义变量,例如表名、列明和LIMIT子句中。
- 用户自定义变量的生命周期是在一个连接(session)中有效,所以不能用它们来做连接间的通信。
- 如果使用连接池或者持久化连接,自定义变量可能让看起来毫无关系的代码发送交互(如果是这样,通常是代码bug或者连接池bug)。
- 不能显式地声明自定义变量的数据类型。
- MySQL优化器在某些场景下可能会将这些变量优化掉。
- 赋值的顺序和赋值的时间点并不总是固定的,这依赖于优化器的决定。
- 赋值符号:=的优先级非常低,所以赋值表达式应该使用明确的括号。
高性能MySQL笔记 第6章 查询性能优化的更多相关文章
- 高性能MySQL(五):查询性能优化
当向MySQL 发送一个请求的时候MySQL 到底做了什么? 1.客户端发送一条查询给服务器 2.服务器先检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果.否则进入下一阶段 3.服务器端进行 ...
- 高性能mysql 第六章查询性能优化 总结(上)查询的执行过程
6 查询性能优化 6.1为什么查询会变慢 这里说明了的查询执行周期,从客户端到服务器端,服务器端解析,优化器生成执行计划,执行(可以细分,大体过程可以通过show profile查看),从服务器端返 ...
- 高性能MySQL笔记 第5章 创建高性能的索引
索引(index),在MySQL中也被叫做键(key),是存储引擎用于快速找到记录的一种数据结构.索引优化是对查询性能优化最有效的手段. 5.1 索引基础 索引的类型 索引是在存储引擎层而 ...
- 高性能mysql 第6章 查询性能优化
查询缓存: 在解析一个sql之前,如果查询缓存是打开的,mysql会去检查这个查询(根据sql的hash作为key)是否存在缓存中,如果命中的话,那么这个sql将会在解析,生成执行计划之前返回结果. ...
- 高性能MySQL笔记 第4章 Schema与数据类型优化
4.1 选择优化的数据类型 通用原则 更小的通常更好 前提是要确保没有低估需要存储的值范围:因为它占用更少的磁盘.内存.CPU缓存,并且处理时需要的CPU周期也更少. 简单就好 简 ...
- 高性能MySQL笔记-第5章Indexing for High Performance-004怎样用索引才高效
一.怎样用索引才高效 1.隔离索引列 MySQL generally can’t use indexes on columns unless the columns are isolated in t ...
- 高性能MySQL笔记-第1章MySQL Architecture and History-001
1.MySQL架构图 2.事务的隔离性 事务的隔离性是specific rules for which changes are and aren’t visible inside and outsid ...
- 高性能MySQL笔记-第5章Indexing for High Performance-002Hash indexes
一. 1.什么是hash index A hash index is built on a hash table and is useful only for exact lookups that u ...
- 高性能MySQL笔记-第5章Indexing for High Performance-001B-Tree indexes(B+Tree)
一. 1.什么是B-Tree indexes? The general idea of a B-Tree is that all the values are stored in order, and ...
随机推荐
- Java主要知识结构
Java基础(建议看java编程规范): Java语言基础:数据类型,命名规则,权限控制符,注释 操作符:算术操作符,逻辑操作符,关系操作符,移位操作符,按位操作符 流程控制 数组 字符串 Java高 ...
- OpenWRT学习笔记-1@WNDR3800
很久以前买了一台二手wndr3800 放假了刷成op可以一耍.ar71xx,芯片还比较热门. 首先是刷机,准备使用OP CC 15.05 r46767,官方稳定版.把原装系统降级到1.0.0.16,就 ...
- sso demo mysql ( cas )
基本配置 参考之前得随笔 http://www.cnblogs.com/rocky-fang/p/5354947.html 1. tomcat-cas 修改配置 1.1 在D:\test\sso\t ...
- php ci 2.0框架 ORM
很早知道ci出了2.0版本了.这几天正好有项目要用ci开发 虽然项目不大.不过也从开发项目的过程中熟悉了CI框架 因为是个电商项目 本来想用个YII2 的. 封装的虽然厉害不过功能强大 因为另个兄弟坚 ...
- 使用OCR来帮助LR实现认证码识别
位字符或数字,如果不是继续刷新,从请求角度来说应该效率很理想了. Action() { int flen; //定义一个整型变量保存获得文件的大小 long filedes; //保存文件句柄 ]=& ...
- EF+MySQL乐观锁控制电商并发下单扣减库存,在高并发下的问题
下订单减库存的方式 现在,连农村的大姐都会用手机上淘宝购物了,相信电商对大家已经非常熟悉了,如果熟悉电商开发的同学,就知道在买家下单购买商品的时候,是需要扣减库存的,当然有2种扣减库存的方式, 一种是 ...
- 记一次CSR上线及总结
终于到上线的时候了,可以好好休息了.放松了,但在没有经过用户确认之前,一切皆有可能发生...... 经历: 项目终于完成,上线文档已准备就绪,等待上线时刻. 在上线之前,忘记了解目前环境的部署架构,注 ...
- bootstrap字体图标在谷歌显示正常,在火狐显示异常的问题
bootstrap字体图标的使用 现在有很多的网站支持字体图标,我所知道的有bootstrap,fontawesome,iconmoon,等等,可能还有其他我并不知道 bootstrap只要你的文件夹 ...
- Dynamics.js - 创建逼真的物理动画的 JS 库
Dynamics.js 是一个用来创建物理动画 JavaScript 库.你只需要把dynamics.js引入你的页面,然后就可以激活任何 DOM 元素的 CSS 属性动画,也可以用户 SVG 属性. ...
- 学习使用 SVG 创建材料设计涟漪(Ripple)效果
Codrops 上面发布了一个深入的教程,就如何建立谷歌材料设计的径向操作规范中列出的涟漪效果,并基于 SVG 和 GreenSock 来实现.随着谷歌的材料设计的出现,带来了一个视觉语言,创建跨平台 ...