• MySQL慢查询的原因与解决方案


    图片

    一、前言

    在数据库系统中,慢查询是一个常见的问题。特别是在MySQL中,由于其复杂的查询结构和大量的数据,慢查询可能会导致系统性能下降,甚至影响整个应用的运行。本文将详细介绍MySQL慢查询的原因,并提供一些有效的解决方案。

    二、MySQL查询的原理流程

    MySQL的查询处理过程大致可以分为以下几步:

    1. 解析:MySQL接收到SQL查询请求后,首先会对SQL语句进行词法、语法解析,生成一颗查询执行树。

    2. 优化:根据查询优化器的规则,对查询树进行优化,如决定是否使用索引,选择最优的连接方式等。

    3. 执行:通过存储引擎执行查询树,获取数据。

    4. 返回结果:将查询结果返回给客户端。

    三、MySQL语句查询指标

    在分析慢查询时,我们通常需要关注以下几个指标:

    响应时间:即从发送查询请求到接收到查询结果的时间。

    锁定时间:即在等待表锁的过程中,其他查询无法进行的时间。

    行数:即扫描的行数。

    通过对这些指标的分析,我们可以初步判断出查询是否可能出现慢查询。

    四、分析 MySQL 语句

    分析 MySQL 语句主要包括以下几个步骤:

    1. 查看执行计划:通过 EXPLAIN 命令可以查看 MySQL 的执行计划,从而了解 SQL 语句的执行过程。

    2. 使用慢查询日志:开启慢查询日志,可以记录所有的 SQL 语句及其执行时间,通过分析慢查询日志,可以找到慢查询的原因。

    3. 使用性能监控工具:如 SHOW PROCESSLIST、SHOW STATUS 等命令,可以查看当前数据库的状态,以及各个连接的状态和运行时间。

    五、开启慢查询

    MySQL慢查询是指响应时间超过一定阈值的SQL语句。在MySQL中,可以通过设置long_query_time参数来指定运行时间超过该值的SQL语句会被记录到慢查询日志中。默认情况下,long_query_time的值为10,意思是记录运行10秒以上的语句。如果您想记录运行时间更长的语句,可以修改该参数的值。

    如果您想查看MySQL中的慢查询日志,可以按照以下步骤进行操作:

    1. 在 MySQL 中,开启慢查询功能很简单,我们只需要在 MySQL 的配置文件中添加以下参数:

    1. log-slow-queries = /var/log/mysql/mysql-slow.log
    2. long_query_time = 1

    其中,log-slow-queries 参数用于指定慢查询日志文件的路径和文件名,long_query_time 参数用于指定查询时间的阈值,单位为秒。在这个例子中,查询时间超过 1 秒钟的查询都会被写入慢查询日志文件。

    2. 在添加这两个参数之后,我们需要重新启动 MySQL 服务,以便应用新的配置。在 CentOS 系统中,我们可以使用以下命令重启 MySQL 服务:

    systemctl restart mysqld

    当然,这个命令也可能因为系统不同而不同,请根据具体情况进行调整。

    六、EXPLAIN执行计划

    使用 Explain 关键字可以模拟优化器执行SQL语句,分析你的查询语句或是结构的性能瓶颈。通过 Explain 可以知道表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息。在 select 语句之前增加 explain 关键字 ,MySQL 会在查询上设置一个标记,执行查询会返回执行计划的信息。

    图片

    结果字段说明:

    1. id 列

    id列的编号是select的序列号,有几个 select 就有几个id,并且id的顺序是按 select 出现的顺序增长的。

    • id列越大执行优先级越高

    • id相同则从上往下执行

    • id为NULL最后执行

    2. select_type 列

    表示简单还是复杂的查询

    • simple:简单查询。说明没有子查询和union

    • primary:复杂查询中,最外层的select

    • subquery:包含在 select 中的子查询

    • derived:包含在 from 中的子查询

    3. table 列

    这一列表示 explain 的一行正在访问哪个表

    4. type列 

    这一列表示访问类型,也就是mysql 查当前行底层是如何执行的

    最优到最差排序:NULL > system > const > eq_ref > ref > range > index > ALL

    5. possible_keys 列

    会用到的索引

    6. key 列

    mysql 真正执行的时候用到的索引

    7. key_len 列

    这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

    8. ref 列

    就是索引关联查询的这个字段,表示查找值所用到的列或者常量,常见有:const(常量)、字段名

    9. rows 列

    这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。这个行数只能作为一个参考值,并不是扫描多的就比行数扫描少的效率低。

    10. Extra 列

    这一列展示的是额外信息

    七、慢查询原因与解决方案

    1. 缺少索引

    如果查询没有使用索引,MySQL必须对整个表进行全扫描,这通常非常耗时。​​​​​​​

    1. -- 缺少索引的例子
    2. SELECT * FROM sys_user WHERE age = 30;

    解决方案:为常用的查询字段添加索引。

    1. -- 添加索引的例子
    2. CREATE INDEX idx_age ON users(age);

    2. 查询语句优化

    复杂的查询,如包含子查询、连接操作或者使用了函数和表达式的查询,通常比简单查询更慢。

    1. -- 复杂查询的例子
    2. SELECT * FROM orders WHERE order_date > (SELECT MAX(order_date) FROM orders);

    解决方案:尽可能避免复杂查询,或者尝试重写为更有效的形式。

    1. -- 优化后的例子
    2. SELECT o.* FROM orders o JOIN (SELECT MAX(order_date) as max_date FROM orders) t ON o.order_date > t.max_date;

    3. 大表扫描

    如果表中的数据量非常大,那么MySQL可能会选择跳过一部分行来提高性能,这被称为"大数据扫描"或"外键扫描"。

    1. -- 大表扫描的例子
    2. SELECT * FROM orders WHERE customer_id = 12345;

     解决方案:如果可能,尝试增加索引列的大小或创建覆盖索引。

    1. -- 增加索引列大小的例子
    2. ALTER TABLE orders MODIFY COLUMN customer_id BIGINT(20);

    4. 硬件限制

    如果服务器的硬件(如CPU、内存或磁盘I/O)不足,那么查询可能会变慢。

    解决方案:根据需要升级硬件。对于MySQL,可以考虑增加缓存大小或调整配置参数以改善性能。

    5. 配置不当

    如果MySQL的配置参数设置得不合理,也可能导致查询变慢。例如,如果缓冲区大小设置得太小,那么MySQL可能会频繁地交换数据到磁盘,这会导致查询速度下降。

    解决方案:根据服务器的硬件资源和应用需求调整配置参数。例如,可以增加innodb_buffer_pool_size的值以提高InnoDB引擎的性能。

    1. -- 调整配置参数的例子
    2. SET GLOBAL innodb_buffer_pool_size = 128M;

    6. SQL注入攻击

    SQL注入攻击可能会导致MySQL执行不必要的操作,从而变慢。预防SQL注入的最佳做法是使用参数化查询或预编译语句。

    解决方案:使用参数化查询或预编译语句,而不是直接在SQL语句中插入用户输入的值。例如:

    1. # Python中使用MySQL Connector库防止SQL注入的示例
    2. import mysql.connector
    3. cnx = mysql.connector.connect(user='username', password='password', host='127.0.0.1', database='test')
    4. cursor = cnx.cursor()
    5. query = "SELECT * FROM users WHERE id = %s" # %s被参数替代
    6. cursor.execute(query, (user_id,)) # user_id是用户输入的值

    7. 缺乏统计信息

    如果MySQL没有关于表的统计信息,那么它可能无法有效地使用索引,导致查询变慢。你可以通过ANALYZE命令更新这些统计信息。

    1. -- 更新统计信息的例子
    2. ANALYZE TABLE orders;

    8. 使用错误的存储引擎

    MySQL支持多种存储引擎,每种引擎都有其优点和缺点。如果你的查询需要特定的功能,但你选择了不支持这些功能的存储引擎,那么查询可能会变慢。例如,MyISAM引擎在处理大量读取操作时性能很好,但在处理写入操作时性能较差。相反,InnoDB引擎在这两方面都表现得很好。

    解决方案:确保你了解你的查询需求,并选择适合的存储引擎。如果需要,你还可以在运行时更改存储引擎。例如:

    1. -- 更改存储引擎的例子(在启动时)
    2. SET storage_engine=INNODB; --或者是MYISAM,根据你的需求选择

    八、总结

    总的来说,MySQL慢查询可能是由多种因素导致的,包括缺乏索引、复杂的查询、大量的数据、硬件限制和配置不当等。解决这个问题需要我们从多个角度出发,比如优化SQL语句、添加合适的索引、增加硬件资源和调整配置等。通过这些方法,我们可以有效地提高MySQL的查询速度,从而提高整个系统的性能。

    图片

  • 相关阅读:
    SpringCloud 微服务接口限流的两种方式
    《最新出炉》系列入门篇-Python+Playwright自动化测试-8-上下文(Context)
    数仓搭建-ODS层
    TIPC Service and Topology Tracking4
    SHELL (bash)编程记录
    子切片的长度和容量
    【正点原子FPGA连载】 第三章 硬件资源详解 摘自【正点原子】DFZU2EG/4EV MPSoC 之FPGA开发指南V1.0
    host以及其作用
    线性代数学习笔记5-4:点积、叉积与线性变换、线性空间理论与傅里叶级数的内在关系
    linux yum源被禁用,yum源管理
  • 原文地址:https://blog.csdn.net/weixin_40381772/article/details/133806503