mysql-查询性能优化

一、不要取出所有列,取出所有列,会让优化器没法完成索引覆盖扫描这类优化,还会为服务器带来额外的I/O、内存和CPU的消耗。应该严格禁止SELECT * 的写法。MySQL使用以下三种方式应用WHERE条件,从好到坏依次为:服务器

  1.1 在索引中使用WHERE条件来过滤不匹配的记录。这是在存储引擎层完成的。性能

  1.2 使用索引覆盖扫描(Extra列中出现了Using index)来返回记录,直接从索引中过滤不须要的记录并返回命中的结果。这是在MySQL服务器层完成的,但无须在回表查询记录。优化

  1.3 从数据表中返回数据,而后过滤不知足条件的记录(在Extra列中出现Using Where)。这在MySQL服务器层完成,MySQL须要先从数据表独处记录而后过滤。spa

上面的例子说明了好的索引很重要。code

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

  2.1 使用索引覆盖扫描,把全部须要用的列都放到索引中,这样存储引擎无须回表获取对应行就能够返回结果了。排序

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

  2.3 重写这个复杂的查询,让MySQL优化器可以以更优化的方式执行这个查询。内存

重构查询:class

  一、一个复杂查询仍是多个简单查询;

  二、切分查询;

  例如:

DELECT FROM message WHERE created < DATE_SUB(NOW(),INTERVAL 3 MONTH);

改为:

rows_affected=0
do{
    rows_affected=do_query(
        "DELECT FROM message WHERE create created < DATE_SUB(NOW(),INTERVAL 3 MONTH) LIMIT 10000"
    )
} while rows_affected > 0

  一次删除一万行数据通常来讲比较高效,若是每次删除数据后,都暂停一下子再作下一次删除,这样也能够将服务器上本来一次性的压力分散到一个很长的时间段中,能够大大的减小对服务器的影响

  三、分解关联查询

查询优化处理

  查询优化处理包括多个子阶段:解析SQL、预处理、优化SQL执行计划。这个过程当中的任何错误(例如语法错误)均可能终止查询。

  优化策略能够简单的分为两种:

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

  二、动态优化:动态优化跟查询上下文有关,也可能和不少其余因素有关,例如WHERE条件中的取值、索引中条目对应的数据行数等。

  MySQL可以处理的优化类型:

  • 从新定义关联表的顺序。
  • 将外链接转化成内链接。
  • 使用等价变换规则。
  • 优化COUNT()、MIN()和MAX()。
  • 预估并转化为常数表达式
  • 覆盖索引扫描
  • 子查询优化
  • 提早终止查询
  • 等值传播
  • 列表IN()的比较

  怎么查看优化器重写后的SQL?

  用到了explain extended和showwarnings

  用ORDER BY排序,若是查询中有LIMIT的话,LIMT也会在排序以后应用,因此即便须要返回较少的数据,历史表和须要排序的数据量仍然会很是大。MySQL5.6在这里作了不少重要的改进。当只须要返回部分排序结果的时候,例如使用LIMIT子句,MySQL再也不对全部的结果进行排序,而是根据实际状况,选择抛弃不知足条件的结果,而后再进行排序。

参考:

[1]Baron Schwartz等 著,宁海元等 译 ;《高性能MySQL》(第3版); 电子工业出版社 ,2013