• 技术文章 >数据库 >mysql教程

    总结分享之mysql慢查询优化的思路

    WBOYWBOY2022-10-12 17:21:45转载487
    本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于慢查询优化的相关问题,包括了利用慢查询日志定位慢查询SQL、通过explain分析慢查询SQL、修改SQL尽量让SQL走索引,下面一起来看一下,希望对大家有帮助。

    php入门到就业线上直播课:进入学习

    推荐学习:mysql视频教程

    1 慢查询优化思路

    当发生慢查询的时候,优化的思路为:

    2 慢查询日志

    MySQL 提供了一个功能——慢查询日志,会记录查询时间超过指定时间阈值的 SQL 到日志中,便于我们定位慢查询并且优化对应的 SQL 语句。

    首先查看 MySQL 中关于慢查询相关的全局变量:

    mysql> show global variables like '%quer%';
    +----------------------------------------+-------------------------------+
    | Variable_name                          | Value                         |
    +----------------------------------------+-------------------------------+
    | binlog_rows_query_log_events           | OFF                           |
    | ft_query_expansion_limit               | 20                            |
    | have_query_cache                       | YES                           |
    | log_queries_not_using_indexes          | OFF                           |
    | log_throttle_queries_not_using_indexes | 0                             |
    ==========================================================================
    | long_query_time                        | 10.000000                     |【1】慢查询的时间阈值
    ==========================================================================
    | query_alloc_block_size                 | 8192                          |
    | query_cache_limit                      | 1048576                       |
    | query_cache_min_res_unit               | 4096                          |
    | query_cache_size                       | 16777216                      |
    | query_cache_type                       | OFF                           |
    | query_cache_wlock_invalidate           | OFF                           |
    | query_prealloc_size                    | 8192                          |
    ==========================================================================
    | slow_query_log                         | OFF                           |【2】慢查询日志是否开启
    | slow_query_log_file                    | /var/lib/mysql/Linux-slow.log |【3】慢查询日志文件存储位置
    ==========================================================================
    +----------------------------------------+-------------------------------+
    15 rows in set (0.00 sec)

    这里主要关注三个变量:

    默认慢查询日志功能是关闭的,因此我们需要启动该功能

    # 开启慢查询日志
    mysql> set global slow_query_log=ON;
    Query OK, 0 rows affected (0.00 sec)
    # 设置慢查询时间阈值
    mysql> set long_query_time=1;
    Query OK, 0 rows affected (0.00 sec)

    这样子设置后,MySQL 重启会丢失这些配置,需要在配置文件中修改才会永久有效。

    3 explain

    我们可以使用 explain 分析 SQL 语句的执行情况,例如:

    mysql> explain select sum(1+2);

    执行结果如下,可以看到有很多字段

    24.png

    我们主要看看一些重要的字段:

    3.1 select_type 字段

    25.png

    3.2 type 字段

    对于 InnoDB 存储引擎,type列通常都是all或者index。

    关于 type 字段的值,其从上到下对应的 SQL 的执行性能逐渐变差。

    26.png

    3.3 extra 字段

    27.png

    4 慢查询例子

    准备数据,数据表结构:

    create table user_info_large (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
    `account` VARCHAR(20) NOT NULL COMMENT '用户账号',
    `name` VARCHAR(20) NOT NULL COMMENT '用户名',
    `password` VARCHAR(20) not null COMMENT '用户密码',
    `area` VARCHAR(20) NOT NULL COMMENT '用户地址',
    `signature` VARCHAR(50) not null COMMENT '个性签名',
    PRIMARY KEY (`id`) COMMENT '主键',
    UNIQUE (`account`) COMMENT '唯一索引',
    KEY `index_area_signture` (`area`,  `signature`)  COMMENT '组合索引'
    );

    随机生成 200w 条数据

    mysql> select count(id) from user_info_large;
    +-----------+
    | count(id) |
    +-----------+
    |   2000000 |
    +-----------+
    1 row in set (0.38 sec)

    截取部分数据:

    28.png

    执行以下 SQL 语句,没有使用任何索引字段:

    SELECT name from user_info_large ORDER BY name desc limit 0,100000;

    Navicat 工具显示的查询时间如下,这并不是 MySQL 真正执行 SQL 的时间,这里面包含了网络传输等时间:

    29.png

    SQL 具体的查询时间可以查看慢查询日志:

    # Time: 2022-09-26T13:44:18.405459Z
    # User@Host: root[root] @  [ip]  Id:  1893
    # Query_time: 10.162999  Lock_time: 0.000113 Rows_sent: 100000  Rows_examined: 2100000
    SET timestamp=1664199858;
    SELECT name from user_info_large ORDER BY name desc limit 0,100000;

    关于其中一些信息的说明:

    正在执行的慢查询是不会被记录到慢查询日志的,只有等待其执行完毕才会记录到日志中。

    我们可以使用 show processlist 查看正在执行 SQL 的线程。

    再执行以下语句,使用索引 account 字段:

    SELECT account from user_info_large ORDER BY account desc limit 0,100000;

    查看慢查询日志,并没有被记录下来。

    现在分别使用 explain 查看 SQL 语句的执行情况:

    explain SELECT name from user_info_large ORDER BY name desc limit 0,100000;

    分析情况如下:

    30.png

    可以看到没有使用到索引,type 为 ALL 表示全表扫描,效率最差,并且 Extra 也是外部排序。

    再看看这条 SQL 语句:

    explain SELECT account from user_info_large ORDER BY account desc limit 0,100000;

    分析情况如下:

    31.png

    type 为 index,使用了索引,使用的索引字段为 account,Extra 显示为使用索引排序。

    因此,在实际开发中,我们可以针对慢查询的 SQL,使用 explain 分析语句,根据分析情况以及索引的设计,重新设计 SQL 语句,让 SQL 语句尽量走索引,走合适的索引。

    5 优化器与索引

    在执行 SQL 时,MySQL 的优化器会根据情况选择索引,但并不能保证其执行时间一定最短,我们可以根据实际情况使用 force key (index) 让 SQL 语句强制走某个索引。

    例如,以下语句执行后,key 字段为 account,并没有走主键索引。

    explain SELECT count(id) from user_info_large;

    32.png

    如果使用 force key,就可以强制令语句走主键索引。

    explain SELECT count(id) from user_info_large force key (PRIMARY);

    33.png

    6 总结

    在项目中如果发现部分 SQL 语句执行缓慢,等待查询时间长,可以考虑优化慢查询,具体思路为:

    在使用 explain 时,我们主要关注这些字段:

    在编写 SQL 使用索引的时候,我们尽量注意一下规则:

    推荐学习:mysql视频教程

    以上就是总结分享之mysql慢查询优化的思路的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金,如有侵犯,请联系admin@php.cn删除

    千万级数据并发解决方案(理论+实战):点击学习

    Mysql单表千万级数据量的查询优化与性能分析

    Mysql主从原理及其在高并发系统中的应用

    专题推荐:mysql
    上一篇:深入探究MySQL中 UPDATE 的使用细节 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• MySQL慢查询日志实操(图文解析)• MySQL怎么优化性能?优化技巧分享• 归纳整理关于mysql left join查询慢时间长的踩坑• 聊聊GitHub是怎么做好 MySQL 高可用性的• 深入探究MySQL中 UPDATE 的使用细节
    1/1

    PHP中文网