慢查询
MySQL慢查询是指执行时间超过阈值的SQL语句,这些慢查询会严重影响数据库的性能。
主要的特点包括:
- 执行时间超过了mysql设置的long_query_time阈值,默认是10秒。
- 不会被MySQL的查询缓存命中,需要每次都经过查询优化器优化然后执行。
- 需要扫描大量的数据行或者访问大量的表。
- 由于表结构设计不合理,导致执行计划低效。
- 服务器参数设置不当,导致系统资源不足,响应慢。
慢查询的主要危害包括:
- 使得用户的请求响应时间过长,直接影响到用户体验。
- 任务队列会因执行慢查询而阻塞,造成资源浪费,其他查询等待。
- 慢查询会占用大量CPU及IO资源,造成系统拥堵。
- 极端情况下可能会造成连接数用尽,服务不可用。
所以数据库应该监控和发现慢查询,并及时进行SQL调优或者架构优化,以提升系统性能。
排查
排查MySQL慢查询的常用方法有:
- 开启并查看慢查询日志,慢查询日志记录了所有执行时间超过阈值的SQL语句,可以找出主要的慢查询SQL。
- 使用show processlist命令查看当前正在执行的线程,找出执行时间过长的线程。
- 对重点慢查询进行EXPLAIN分析,查看查询执行计划,判断执行过程中是否存在全表扫描、缺失索引等情况。
- 使用show profiles和show profile for query命令查看SQL执行过程中的每个步骤所消耗的时间,定位慢查询的具体原因。
- 分析慢查询的SQL语句本身,检查是否可以进行SQL优化,例如添加索引、调整连接条件等。
- 检查数据库服务器参数配置,确保key_buffer_size、query_cache大小等系统参数设置合理,避免成为瓶颈。
- 使用trace工具跟踪记录慢查询的整个执行过程,进一步找出性能瓶颈。
- 检查磁盘IO情况,判断磁盘读写性能是否是慢查询的原因。
- 使用升级更高配置的服务器,测试性能提升情况,判断硬件资源是否限制了数据库性能。
通过综合运用这些排查手段,可以确定慢查询的具体原因,针对性地进行SQL优化和系统调优以提高查询性能。
EXPLAIN分析
EXPLAIN命令在MySQL中可以用于分析SELECT查询语句的执行计划,以检查 SQL 语句性能瓶颈。
使用EXPLAIN命令可以查看以下信息:
- select_type:查询类型,包括SIMPLE、PRIMARY、UNION等。
- table:查询是关联的表。
- partitions:匹配的表分区。
- type:访问类型,包括全表扫描、索引查找等。
- possible_keys:此查询可使用的索引。
- key:实际使用的索引。
- key_len:使用索引字段的长度。
- rows:预计扫描的行数。
- filtered:查询条件过滤出的行数比例。
- extra:额外信息。
通过分析这些信息,可以检查查询是否存在全表扫描、索引是否被使用、扫描行数是否过多等情况,来判断及优化查询性能。
EXPLAIN SELECT * FROM employees WHERE salary > 10000;
show processlist 命令
show processlist是MySQL提供的一个显示当前连接线程信息的命令。
show processlist显示内容包括:
- Id - 连接的ID号
- User - 用户名
- Host - 客户端的IP地址
- db - 连接所使用的数据库名
- Command - 线程正在执行的命令类型
- Time - 线程已执行的时间
- State - 线程当前所处的状态
- Info - 语句的详细信息
mysql> show processlist;
+----+-------------+-----------------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------------+------+---------+------+-------+------------------+
| 51 | event_sched | localhost:57806 | NULL | Daemon | 1695 | NULL | event scheduler |
| 61 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+-------------+-----------------+------+---------+------+-------+------------------+
show profiles 命令
MySQL中的show profiles命令用于显示最近执行过的语句或函数的资源消耗情况。
show profiles显示的主要信息包括:
- Query_ID:语句的ID号
- Duration:执行事件总时间
- CPU_user:用户态CPU时间
- CPU_system:系统态CPU时间
- Context_voluntary:自愿上下文切换次数
- Context_involuntary:非自愿上下文切换次数
- Block_ops_in:输入块操作次数
- Block_ops_out:输出块操作次数
- Messages_sent:发出消息数
- Messages_received:收到消息数
- Page_faults_major:主要页错误数
- Swaps:交换次数
- Source_function:产生事件的源代码位置
mysql> show profiles;
+----------+----------+--------------------------+
| Query_ID | Duration | Query |
+----------+----------+--------------------------+
| 1 | 0.000219 | show tables |
| 2 | 0.230491 | select * from employees |
+----------+----------+--------------------------+
show profile for query 命令
MySQL中的show profile for query命令可以更详细地显示出一条SQL语句在执行过程中每个状态所消耗的时间和资源使用情况。
show profile for query 需要指定某个查询的Query_ID。查询ID可以通过show profiles命令得到。
show profile for query显示的信息包括:
- Status: SQL执行各个阶段的状态信息
- Duration:每个状态消耗的时间
- CPU_user:用户态CPU时间
- CPU_system:系统态CPU时间
- Context_voluntary:自愿上下文切换次数
- Context_involuntary:非自愿上下文切换次数
- Block_ops_in:输入块操作数
- Block_ops_out:输出块操作数
- Messages_sent:发出的消息数
- Messages_received:收到的消息数
- Page_faults_major:主要页错误数
- Swaps:交换次数
- Source_function:函数名
mysql> show profile for query 2;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000092 |
| checking permissions | 0.000005 |
| Opening tables | 0.000036 |
| init | 0.000052 |
| System lock | 0.000057 |
| optimizing | 0.000010 |
| statistics | 0.000082 |
| preparing | 0.000084 |
| executing | 0.000003 |
| Sending data | 0.213464 |
| end | 0.000037 |
| query end | 0.000006 |
| closing tables | 0.000009 |
| freeing items | 0.000032 |
| cleaning up | 0.000015 |
+----------------------+----------+