字数: 预计阅读时长:

优化方向

:::info 数据库性能优化流程 ::: MySQL调优 - 图1

查看系统性能参数

常见参数

  • Connection: MySQL服务器的连接次数
  • Uptime : 服务器上线时间
  • Slow_queries : 慢查询的条数
    1. show status \G;
    2. mysql> SHOW status like '%slow_queries%';
    3. +---------------+-------+
    4. | Variable_name | Value |
    5. +---------------+-------+
    6. | Slow_queries | 0 |
    7. +---------------+-------+
    8. 1 row in set (0.00 sec)

    查询成本

    ```sql mysql> select * from tb1; +———+———-+ | id | name | +———+———-+ | 1 | name1 | | 2 | name2 | | 3 | name3 | +———+———-+ 3 rows in set (0.00 sec)

mysql> show status like ‘last_query_cost’; +————————-+—————+ | Variable_name | Value | +————————-+—————+ | Last_query_cost | 0.549000 | +————————-+—————+ 1 row in set (0.00 sec)

  1. ```sql
  2. +----------+
  3. | Value |
  4. +----------+
  5. | 0.549000 |
  6. +----------+
  7. # value指这条语句用到的页的数量

:::info SQL查询从页的加载角度看:

  1. 位置决定效率页的位置可能在磁盘 / 内存 / 数据库缓冲池中,缓冲池的效率最高。
  2. IO顺序决定效率顺序IO效率远高于随机IO。 :::

    性能分析工具

    慢查询日志

    相关参数

    超过阈值的为慢查询
    1. mysql> show variables like '%long%query%';
    2. +-----------------+-----------+
    3. | Variable_name | Value |
    4. +-----------------+-----------+
    5. | long_query_time | 10.000000 |
    6. +-----------------+-----------+

慢查询日志默认关闭,通过修改以下参数 [Global | Session] 开启。

  1. mysql> show variables like '%slow_query_log%';
  2. +---------------------+-------------------------------------------+
  3. | Variable_name | Value |
  4. +---------------------+-------------------------------------------+
  5. | slow_query_log | OFF |
  6. | slow_query_log_file | /var/lib/mysql/VM-xavier-CentOS7-slow.log |
  7. +---------------------+-------------------------------------------+
  8. 2 rows in set (0.00 sec)

注意:如果不加Global ,操作的是session级别的变量,下一个会话会失效。

以上修改在mysqld服务重启后失效。 修改/etc/my.cnf 可永久生效


分析工具mysqldumpslow

  1. [root@VM-xavier-CentOS7 mysql]# mysqldumpslow -a -t 5 /var/lib/mysql/VM-xavier-CentOS7-slow.log
  2. Reading mysql slow query log from /var/lib/mysql/VM-xavier-CentOS7-slow.log
  3. Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.0 (0), 0users@0hosts
  4. Died at /usr/bin/mysqldumpslow line 162, <> chunk 1.

查看执行成本:show profile

也可以在 information_schema profiling 表中查看。 :::info 功能开启 ::: 该功能默认关闭,我们可在会话级别开启

  1. mysql> show variables like '%profiling%';
  2. +------------------------+-------+
  3. | Variable_name | Value |
  4. +------------------------+-------+
  5. | have_profiling | YES |
  6. | profiling | OFF |
  7. | profiling_history_size | 15 |
  8. +------------------------+-------+
  9. 3 rows in set (0.00 sec)

:::info 指令演示 :::

  1. mysql> show profiles;
  2. +----------+------------+-----------------------------------+
  3. | Query_ID | Duration | Query |
  4. +----------+------------+-----------------------------------+
  5. | 1 | 0.00174550 | show variables like '%profiling%' |
  6. | 2 | 0.00013850 | select database() |
  7. | 3 | 0.00065250 | show databases |
  8. | 4 | 0.00101425 | show tables |
  9. | 5 | 0.00025675 | select * from tb1 |
  10. +----------+------------+-----------------------------------+
  11. 5 rows in set, 1 warning (0.00 sec)
  1. mysql> show profile for query 5;
  2. +--------------------------------+----------+
  3. | Status | Duration |
  4. +--------------------------------+----------+
  5. | starting | 0.000074 |
  6. | Executing hook on transaction | 0.000005 |
  7. | starting | 0.000007 |
  8. | checking permissions | 0.000007 |
  9. | Opening tables | 0.000030 |
  10. | init | 0.000006 |
  11. | System lock | 0.000009 |
  12. | optimizing | 0.000005 |
  13. | statistics | 0.000012 |
  14. | preparing | 0.000015 |
  15. | executing | 0.000040 |
  16. | end | 0.000005 |
  17. | query end | 0.000004 |
  18. | waiting for handler commit | 0.000007 |
  19. | closing tables | 0.000007 |
  20. | freeing items | 0.000015 |
  21. | cleaning up | 0.000012 |
  22. +--------------------------------+----------+
  23. 17 rows in set, 1 warning (0.00 sec)

EXPLAIN

  • 功能 :查看执行计划。

image.png
image.png

字段解析

Table

  • 每个SELECTFROM子句中可以包含若干张表,每张表都对应执行计划中的一条记录
  • image.png
  • 多表时:靠前的table是驱动表,靠后的是被驱动表 :::info 对Union操作,需要临时表去重 ::: image.png

id

  • 每一个SELECT对应着一个 id 。
  • 同一个SELECT关键字中的表拥有相同的id值
  • 例:子查询 :::info 优化器Optimizer 可能对子查询重写,转为多表查询
    子查询类似与嵌套循环,复杂度为O(n^2)。而多表查询为O(n)。 ::: :::success 小结:
  1. id相同的为一组,从上往下顺序执行
  2. 在所有组中,id值越大,优先级越高 :::

select_type

  • 一个大查询语句包含多个小查询, select_type 指对应的 SELECT的类型。 :::success SIMPLE :::

  • 普通查询,连接查询都是 SIMPLE类型

image.png :::success UNION 操作中的 select_type :::

  • PRIMARY: UNION操作中最左边的SELECT
  • UNION :UNION操作中其他的 SELECT
  • UNION RESULT: 临时表

image.png :::success 不能转为多表连接的子查询 :::

  • 不相关子查询
    • 外层查询select_type为 PRIMARY
    • 内层子查询 select_type 为 SUBQUERY.
  • 相关子查询
    • 外层查询select_type为 PRIMARY
    • 内层子查询 select_type 为 DEPENDENT_SUBQUERY. :::success UNION作为内层查询 :::
      1. SELECT * FROM table3 WHERE XX
      2. IN (SELECT col FROM table1 UNION SELECT col FROM table2);
      | id | Table | select_type | sql | 备注 | | —- | —- | —- | —- | —- | | 1 | table3 | PRIMARY | SELECT FROM table3 | 最外层查询最晚执行 | | 2 | table1 | DEPENDENT_SUBQUERY | SELECT FROM table1 | 子查询先执行 | | 3 | table2 | DEPENDENT_UNION | SELECT * FROM table2 | 子查询先执行 | | NULL | | | | |

:::success Derived :::

  • 场景:用 查询结果 作为FROM子句中的表时,select_type为 DERIVED.
    1. SELECT col FROM (SELECT * FROM tb1 WHERE ...) AS derived_table;
    :::success MATERIALIZED ::: 略。

Type**

  • 标志执行查询时的访问类型


:::info const :::

  • 通过主键或二级索引与常量做等值比较

:::info eq_ref ::: image.png
image.png :::info ref :::

  • 通过普通二级索引与常量做等值比较

:::info index_merge :::

  • 索引合并 (例如 WHERE … OR … 而两个条件都有索引)

:::info Unique_subquery ::: image.pngimage.png

  • 查询优化器可能将 **IN**转为 EXISTS
  • 过程:用ALL访问方式访问 s1 表,key2 的值与 subquery 做等值比较

:::info Range :::

  • 用索引做范围查询

:::info Index :::

  • 当可以使用索引覆盖,但需要scan全部索引记录时,type为**index**.



Key_len

  • key_len :用到的索引长度
  • 注:对联合索引参考价值更大,若联合索引得到充分利用,那么通过where筛选剩下的记录就越少,读取的页就更少,IO次数更少,性能更高。

Ref

  • 当使用索引等值查询时,与索引列进行等值匹配的对象信息。
  • 可能取值
    • const — 等值匹配的是常量
    • db1.tb1.col — 等值匹配的是数据表db1的表tb1的列col
    • func — 函数

Rows**

  • 预估需要读取的行数

Filtered**

  • 过滤百分比

Extra**

  • 额外的执行信息 :::info 详情参见帮助文档 :::

EXPLAIN 格式

:::info JSON格式:可以获取具体的成本信息 :::

  1. mysql> explain format = JSON select * from tb1 where id = 2\G;
  2. *************************** 1. row ***************************
  3. EXPLAIN: {
  4. "query_block": {
  5. "select_id": 1,
  6. "cost_info": {
  7. "query_cost": "1.00"
  8. },
  9. "table": {
  10. "table_name": "tb1",
  11. "access_type": "const",
  12. "possible_keys": [
  13. "PRIMARY"
  14. ],
  15. "key": "PRIMARY",
  16. "used_key_parts": [
  17. "id"
  18. ],
  19. "key_length": "4",
  20. "ref": [
  21. "const"
  22. ]
  23. .....................

:::info TREE :::

  • EXPLAIN FORMAT = TREE […..] ```sql mysql> explain format = Tree select from tb1 where id = 2\G; ** 1. row * EXPLAIN: -> Rows fetched before execution (cost=0.00..0.00 rows=1)

1 row in set (0.00 sec)

  1. ---
  2. <a name="JFqAt"></a>
  3. ### Show warnings
  4. 1. `explain`之后紧接着用 `**show warnings**`
  5. 1. `**message**`是重点,**可以看到mysql 改写后的sql语句**。
  6. ```sql
  7. mysql> explain select * from tb1 where id = 2;
  8. +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
  9. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  10. +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
  11. | 1 | SIMPLE | tb1 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
  12. +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
  13. 1 row in set, 1 warning (0.00 sec)
  14. mysql> show warnings;
  15. +-------+------+--------------------------------------------------------------------------------------+
  16. | Level | Code | Message |
  17. +-------+------+--------------------------------------------------------------------------------------+
  18. | Note | 1003 | /* select#1 */ select '2' AS `id`,'name2' AS `name` from `main_db1`.`tb1` where true |
  19. +-------+------+--------------------------------------------------------------------------------------+
  20. 1 row in set (0.00 sec)

Trace:分析优化器执行计划

  1. mysql> show variables like '%opti%tr%';
  2. +------------------------------+----------------------------------------------------------------------------+
  3. | Variable_name | Value |
  4. +------------------------------+----------------------------------------------------------------------------+
  5. | optimizer_trace | enabled=off,one_line=off |
  6. | optimizer_trace_features | greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on |
  7. | optimizer_trace_limit | 1 |
  8. | optimizer_trace_max_mem_size | 1048576 |
  9. | optimizer_trace_offset | -1 |
  10. +------------------------------+----------------------------------------------------------------------------+
  11. 5 rows in set (0.01 sec)

:::info 该计划信息 在 information_schema 数据库的 OPTIMIZER_TRACE 表中 :::

  1. mysql> show tables like '%opt%';
  2. +--------------------------------------+
  3. | Tables_in_information_schema (%OPT%) |
  4. +--------------------------------------+
  5. | OPTIMIZER_TRACE |
  6. +--------------------------------------+
  7. 1 row in set (0.01 sec)

Sys schema系统视图

:::info 在 Sys 数据库中 有一些便于开发和运维快速定位问题的视图 :::

  1. mysql> show tables like '%ind%';
  2. +---------------------------+
  3. | Tables_in_sys (%ind%) |
  4. +---------------------------+
  5. | schema_index_statistics |
  6. | schema_redundant_indexes |
  7. | schema_unused_indexes |
  8. | x$schema_index_statistics |
  9. +---------------------------+
  10. 4 rows in set (0.00 sec)
  11. mysql> select * from sys.schema_index_statistics limit 1\G;
  12. *************************** 1. row ***************************
  13. table_schema: main_db1
  14. table_name: tb1
  15. index_name: PRIMARY
  16. rows_selected: 5
  17. select_latency: 104.30 us
  18. rows_inserted: 0
  19. insert_latency: 0 ps
  20. rows_updated: 0
  21. update_latency: 0 ps
  22. rows_deleted: 0
  23. delete_latency: 0 ps
  24. 1 row in set (0.00 sec)