zoukankan      html  css  js  c++  java
  • MySQL SQL优化教程

    转自:https://www.cnblogs.com/duanxz/archive/2013/02/01/2889413.html

    一,查询SQL执行效率

    通过show status命令了解各种SQL的执行效率。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    mysql> show status like 'Com_%';
    +---------------------------+-------+
    | Variable_name             | Value |
    +---------------------------+-------+
    | Com_admin_commands        | 0     |
    | Com_assign_to_keycache    | 0     |
    | Com_alter_db              | 0     |
    | Com_alter_db_upgrade      | 0     |
    | Com_alter_event           | 0     |
    | Com_alter_function        | 0     |
    | Com_alter_procedure       | 0     |
    | Com_alter_server          | 0     |
    | Com_alter_table           | 0     |
    | Com_alter_tablespace      | 0     |
    | Com_analyze               | 0     |
    | Com_begin                 | 0     |
    | Com_binlog                | 0     |
    ...

    Com_xxx表示每个xxx语句执行的次数。
    Com_select:执行select操作的次数,一次查询只累加1。
    Com_inset:执行insert操作的次数,对于批量插入的insert操作,只累加一次。
    Com_update:执行update操作的次数。
    Com_delete:执行delete操作的次数。

    通过查询,可以了解当前数据库的应用是以插入更新为主还是以查询操作为主,以及各种类型的SQL大致的执行比例是多少。


    二,定位执行效率较低的SQL语句

    通过慢查询日志定位那么执行效率较低的SQL语句,启用慢查询后,mysqld写一个包含所有执行时间超过long_query_time秒的SQL语句的日志文件。

    慢查询日志在查询结束以后才记录,所以在应用放映执行效率出现问题的时候查询慢查询的日志并不能定位问题。

    1
    2
    3
    4
    5
    6
    7
    mysql> explain select * from employee_tbl where id = 3;
    +----+-------------+--------------+-------+---------------+---------+---------+-------+------+-------+
    | id | select_type | table        | type  | possible_keys | key     | key_len | ref   | rows | Extra |
    +----+-------------+--------------+-------+---------------+---------+---------+-------+------+-------+
    |  1 | SIMPLE      | employee_tbl | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
    +----+-------------+--------------+-------+---------------+---------+---------+-------+------+-------+
    1 row in set

    select_type:表示select的类型,常见的取值有SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个select)等。

    table:输出结果集的表。

    type:表示MySQL在表中找到所需行的方式,或者叫访问类型。

    常见类型,从左至右,性能由最差到最好:

    1
    ALL < index < range < ref < eq_ref < const,system < NULL

    1,type=ALL,全表扫描,MySQL遍历全表来找到匹配的行。
    2,type=index,索引全扫描,MySQL遍历整个索引来查询匹配的行。
    3,type=range,索引范围扫描,常见于<,<=,>,>=,between等操作符。
    4,type=ref,使用非唯一索引扫描或唯一索引的前缀扫描,返回匹配某个单独值的记录行。
    5,type=eq_ref,类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中有一条记录匹配,简单来说,就是多表连接中使用primary key或者unique index作为关联条件。
    6,type=const/system,单表中最多有一个匹配行,查询起来非常迅速,所以这个匹配行中的其他列的值可以被优化器在当前查询中当做常量来处理,例如,根据主键primary key或者唯一索引unique index记性的查询。
    7,type=NULL,MySQL不用访问表或者索引,直接就能够得到结果。


    三,通过show profile分析SQL

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    //查看当前MySQL是否支持profile
    mysql> select @@have_profiling;
    +------------------+
    | @@have_profiling |
    +------------------+
    | YES              |
    +------------------+
    1 row in set
     
    //默认profiling是关闭的,可以通过set语句在session级别开启profiling
    mysql> select @@profiling;
    +-------------+
    | @@profiling |
    +-------------+
    |           0 |
    +-------------+
    1 row in set
     
    mysql> set profiling=1;
    Query OK, 0 rows affected
     
    mysql> show profiles;
    +----------+-----------+-----------------------------------------+
    | Query_ID | Duration  | Query                                   |
    +----------+-----------+-----------------------------------------+
    |        1 | 0.0001725 | select * from employee_tbl where id = 3 |
    +----------+-----------+-----------------------------------------+
    1 row in set
     
    mysql> show profile
     for query 1;
    +--------------------------------+----------+
    | Status                         | Duration |
    +--------------------------------+----------+
    | starting                       | 2.6E-5   |
    | Waiting for query cache lock   | 3E-6     |
    | checking query cache for query | 6E-6     |
    | checking privileges on cached  | 3E-6     |
    | checking permissions           | 7E-6     |
    | sending cached result to clien | 0.000123 |
    | logging slow query             | 4E-6     |
    | cleaning up                    | 2E-6     |
    +--------------------------------+----------+
    8 rows in set

    Sending dat状态表示MySQL线程开始访问数据行并把结果返回给客户端,而不仅仅是返回结果给客户端。由于在Sending data状态下,MySQL线程往往需要做大量的磁盘读取操作,所以经常是整个查询中耗时最长的状态。


    四,通过trace分析优化器如何选择执行计划

    MySQL 5.6提供了对SQL的跟踪trace,通过trace文件能够进一步了解为什么优化器选择A执行计划而不选择B执行计划,帮助我们更好地理解优化器的行为。

  • 相关阅读:
    人月神话
    Rails 最佳实践
    萧伯纳名言名句大全
    听话,照做,执行,别发挥
    So Good They Can't Ignore You
    谈谈遵守公司作战纪律
    如何让自己有动力去长久地做一件事情
    新架构优化问题总结
    Markdown 入门
    关于代码版本管理的思考和建议
  • 原文地址:https://www.cnblogs.com/sharpest/p/9305736.html
Copyright © 2011-2022 走看看