MySQL之查询性能优化一

只有当查询优化,索引优化,库表结构优化齐头并进时,才能实现mysql高性能。mysql

在尝试编写快速的查询以前,须要清楚一点,真正重要是响应时间。sql

 

查询的生命周期数据库

一般来讲,查询的生命周期大体能够按照顺序来看:从客户端->服务器->而后再服务器上进行解析->生成执行计划->执行->并返回结果给客户端。缓存

其中"执行"能够认为是整个生命周期最重要的阶段,这其中包括了大量为了检索数据到存储引擎的调用以及调用后的数据处理,包括排序,分组等。服务器

对于一个查询的所有生命周期,上面列的并不完整。这里咱们只是想说:了解查询的生命周期,清楚查询的时间消耗状况对于优化查询有很大的意义。mysql优化

 

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

  1.是否向数据库请求了不须要的数据性能

  2.mysql是否扫描额外的纪录优化

    查询是否扫描了过多的数据。最简单的衡量查询开销三个指标以下:spa

      响应时间。

      扫描的行数。

      返回的行数。

    没有哪一个指标可以完美地衡量查询的开销,但它们大体反映了mysql在内部执行查询时须要多少数据,并能够推算出查询运行的时间。

    这三个指标都会记录到mysql的慢日志中,因此检查慢日志记录是找出扫描行数过多的查询的好办法。

    响应时间:

      是两个部分之和:服务时间和排队时间。

       服务时间是指数据库处理这个查询真正花了多长时间。

       排队时间是指服务器由于等待某些资源而没有真正执行查询的时间。---多是等io操做完成,也多是等待行锁,等等。

    扫描的行数和返回的行数:

      分析查询时,查看该查询扫描的行数是很是有帮助的。这在必定程度上可以说明该查询找到须要的数据的效率高不高。

    扫描的行数和访问类型:

      在expain语句中的type列反应了访问类型。访问类型有不少种,

      从全表扫描(ALL)到

       索引扫描(index)到

       范围扫描()到

       惟一索引查询 到

       常数引用等。这里列的这些,速度由慢到快,扫描的行数也是从小到大。

    若是发现查询须要扫描大量的数据但只返回少数的行,那么一般能够尝试下面的技巧去优化它:

      使用索引覆盖扫描。

      改变库表结构。例如使用单独的汇总表。

      重写这个复杂的查询。让mysql优化器可以以更优化的方式执行这个查询。

 

一些简单的重构查询的方式:

  1.一个复杂查询 or 多个简单查询

    设计查询的时候一个须要考虑的重要问题是,是否须要将一个复杂的查询分红多个简单的查询。

  2.切分查询

    有时候对于一个大查询咱们须要“分而治之”,将大查询切分为小查询,每一个查询功能彻底同样,只完成一小部分,每次

    只返回一小部分查询结果。

  3.分解关联查询

    select * from tag 

       join tag_post on tag_post.tag_id = tag.id

       join post on tag_post.post_id = post.id

    where tag.tag = 'mysql'

    能够分解成下面这些查询来代替:

    > select * from tag where tag = 'mysql'

    > select * from tag_post where tag_id = 1234

    > select * from post where post_id in (123, 456, 567, 9098, 8904)    

  优点:

      让缓存的效率更高。

      将查询分解后,执行单个查询能够减小锁的竞争。

      在应用层作关联,能够更容易对数据库进行拆分,更容易作到高性能和可扩展。

      查询自己效率也可能会有所提高。

      能够减小冗余记录的查询,

      更进一步,这样作至关于在应用中实现了哈希关联,而不是使用mysql的嵌套循环关联。

 

查询主流程:

  当但愿mysql可以以更高的性能运行查询时,最好的办法就是农清楚mysql是如何优化和查询的。

  一旦理解这一点,不少查询优化工做实现上就是遵循一些原则让优化器可以按照预想的合理的方式运行。

  

1.客户端发送一条查询给服务器

2.服务器先检查查询缓存,若是命中了缓存,则马上返回存储在缓存中的结果,不然进入下一阶段。

3.服务器进行SQL解析,预处理,再由优化器生成对应的执行计划,

4.mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。

5.将结果返回给客户端。

 

MySQL链接状态:

对于一个MYSQL链接,或者说一个线程,任什么时候刻都有一个状态,该状态表示了mysql正在作什么,有不少方式能查看当前
状态,最简单的是使用show full processlist
在一个查询的周期中,状态可能会变化不少次,
这些状态有:
  sleep:
  线程正在等待客户端发送新的请求。

  query:
  线程正在执行查询或者正在将结果发送给客户端。

  locked:
  在mysql服务器层,该线程正在等待表锁。在存储引擎级别实现的锁,
  例如innoDB的行锁,并不会体如今线程状态中。对于myisam来讲这是个比较典型的状态,但在其余没有
  行锁的引擎也常常会出现。

  analyzing and statistics:
  线程正在收集存储引擎的统计信息,并生成查询的执行计划。

  copying to tmp table [on disk]:
  线程正在执行查询,而且将结果集复制到一个临时表,
  这种状态通常要么是在作 group by 操做,要么是文件排序操做,或者是union操做
  若是这个状态后面还有 on disk 标记,那表示mysql正在将一个内存临时表放到磁盘上。

  sorting result:
  线程正在对结果集进行排序

  sending data:
  这表示多种状况,线程可能在多个状态之间传送数据,或者在生成结果集,或者在客户端发送请求。

 

 

总结:

  本文主要介绍了一些关于mysql的查询流程和一些基本术语,这些对理解mysql优化查询会有至关大的帮助。

相关文章
相关标签/搜索