为什么不记录慢查询?

本文记录了一次因长时间运行的SQL事务导致前端玩家出现掉线的问题排查过程。通过查看InnoDB事务状态,发现一执行超过1小时的SQL未正常结束,Kill进程后问题解决。分析得出,仅当Query_time-Lock_time超过long_query_time阈值时,SQL才会被记录到慢查询日志。
㈠ 背景介绍:
  
  2014/8/18 13点37分收到前端说反馈有玩家掉线情况,检查CPU、慢查询、DB请求量,并未发现异常,DB表现一如往常。


㈡ 定位原因:

INSERT INTO t (col1, col2, col3, col4, col5, col6, col7) VALUES ('3532082239485507011_130_99', '130_99', 130, 99, 3532082239485507011, 2172353000317425008, 29078) 

这个长事务执行 1个多小时没有退出,Kill 掉对应的进程,程序前端恢复正常


㈢ 处理思路:

  ⑴ 查询视图

select trx_id,trx_state,trx_started,trx_requested_lock_id,trx_weight,trx_mysql_thread_id from information_schema.innodb_trx where trx_state='RUNNING';

  ⑵ show engine innodb status\G; 关注Transactions部分提取SQL及事务信息
  

㈣ 我的疑问:


为什么这条执行了1个多小时的SQL没有被记录到慢查询日志中呢??


㈤ 原来如此:


Query_time - Lock_time > long_query_time  <===记录
Query_time - Lock_time < long_query_time  <===不记录



㈥ 模拟场景:


⑴ Query_time - Lock_time > long_query_time

Session_A:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select emp_no,hire_date from employees where emp_no=10170 for update;
+--------+------------+
| emp_no | hire_date  |
+--------+------------+
|  10170 | 1986-01-02 |
+--------+------------+
1 row in set (0.00 sec)

Session_B:

mysql> select emp_no,hire_date,sleep(3) from employees where emp_no=10170 for update;


过段时间在A做commit,B会执行、并被记录到slow log中:

# Time: 140818 22:37:31
# User@Host: root[root] @ localhost []  Id:     1
# Query_time: 3.049016  Lock_time: 0.018891 Rows_sent: 1  Rows_examined: 1
use employees;
SET timestamp=1408372651;
select emp_no,hire_date,sleep(3) from employees where emp_no=10170 for update;




⑵ Query_time - Lock_time < long_query_time

Session_A:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select emp_no,hire_date from employees where emp_no=10170 for update;
+--------+------------+
| emp_no | hire_date  |
+--------+------------+
|  10170 | 1986-01-02 |
+--------+------------+
1 row in set (0.00 sec)

Session_B:

mysql> select emp_no,hire_date from employees where emp_no=10170 for update;

过段时间在A做commit,B会执行、但不会被记录到slow log中


㈦ 我的收获:

我们日常做性能剖析实际上应该包括2个方面:

1)基于执行时间的分析

2)基于等待时间的分析


By water

Good Luck!


<think>我们正在讨论MySQL查询性能优化。用户的问题有两个部分:为什么查询速度慢,以及如何优化。 根据引用内容,查询速度慢的常见原因包括: 1. 访问的数据太多(引用[2]) 2. 查询写得很糟糕(引用[3]) 3. 数据量大时,一次性查询所有结果会变慢(引用[4]) 优化方向: 1. 减少访问的数据量(例如,只选择必要的列,使用LIMIT分页) 2. 优化查询语句(避免复杂的子查询,使用JOIN优化等) 3. 建立合适的索引(引用[1]提到索引的重要性) 4. 分页查询优化(引用[4]提到分页查询的优化方法) 具体到用户的问题,我们需要分析具体的查询语句,但用户没有提供具体的SQL。因此,我们给出一般性的建议。 步骤: 1. 分析查询:使用EXPLAIN分析查询计划,查看是否使用了索引,扫描的行数等。 2. 优化索引:确保WHERE条件、JOIN条件、ORDER BY等涉及的列上有合适的索引。 3. 重写查询:避免使用SELECT *,只选择需要的列;将子查询改写为JOIN;避免在WHERE子句中对列进行函数操作等。 4. 分页优化:对于大偏移量的分页,避免使用OFFSET,而是使用WHERE条件定位。 例如,分页优化: 传统分页:SELECT * FROM table LIMIT 10000, 10; -- 偏移量很大时,会扫描前10010行然后丢弃前10000行 优化方法:可以记录上一页的最大ID,然后使用WHERE id > last_id LIMIT 10; 另外,引用[2]提到减少额外、重复的操作,比如避免重复查询相同的数据,使用缓存等。 因此,我们可以这样组织回答: 1. 解释为什么查询慢(数据量大,访问数据多,没有索引等) 2. 给出优化方法(索引优化,查询语句优化,分页优化等) 3. 建议使用EXPLAIN工具分析 同时,根据系统指令,我们需要在回答中自然地添加引用标识,并在最后生成相关问题。 注意:回答中引用的段落末尾添加引用标识,例如:[^1]</think>### MySQL查询性能优化分析 #### 为什么查询速度慢? 1. **数据访问量过大** 当查询需要扫描大量数据时(如全表扫描),性能会急剧下降。例如没有索引的`WHERE`条件或`SELECT *`操作,会导致数据库读取冗余数据[^2][^3]。 2. **索引缺失或失效** 未建立合适索引、索引统计信息过期、或在查询中对列使用函数(如`WHERE YEAR(create_time)=2023`)会导致索引失效[^1][^3]。 3. **低效的查询设计** 复杂的嵌套子查询、非必要的`DISTINCT`或`ORDER BY`操作、隐式类型转换(如字符串与数字比较)会增加计算开销[^3]。 4. **分页深度偏移** 类似`LIMIT 10000,10`的查询需要先扫描前10000条记录,大偏移量时性能骤降[^4]。 5. **锁竞争与资源瓶颈** 长时间运行的查询可能阻塞其他操作,同时内存足或磁盘I/O瓶颈也会拖慢响应[^1]。 --- #### 优化方案 1. **索引优化** - 为高频查询条件列创建索引,例如: ```sql ALTER TABLE orders ADD INDEX idx_user_id (user_id); ``` - 使用覆盖索引(索引包含所有查询字段),避免回表操作。 2. **查询重写** - 避免`SELECT *`,明确指定所需字段: ```sql SELECT id, name FROM users WHERE status=1; -- 代替 SELECT * ``` - 将子查询转化为`JOIN`: ```sql SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id -- 替代子查询 WHERE o.amount > 1000; ``` 3. **分页优化** - 使用游标分页(基于有序唯一值): ```sql SELECT * FROM logs WHERE id > 10000 -- 替代 LIMIT 10000,10 ORDER BY id LIMIT 10; ``` 4. **减少计算量** - 避免在`WHERE`子句中使用列运算: ```sql SELECT * FROM sales WHERE sale_date > '2023-01-01'; -- 代替 WHERE YEAR(sale_date)=2023 ``` 5. **分析执行计划** 使用`EXPLAIN`诊断问题: ```sql EXPLAIN SELECT * FROM products WHERE category_id = 5; ``` 关注`type`(扫描类型)、`rows`(预估扫描行数)、`key`(使用索引)等字段[^1][^3]。 --- #### 性能监控工具 - **慢查询日志**:启用`slow_query_log`捕获低效SQL。 - **Performance Schema**:分析查询执行细节。 - **pt-query-digest**:对慢查询日志进行聚合分析。 > 优化效果案例:某电商平台将分页查询从`LIMIT offset,N`改为游标分页后,响应时间从**2.1秒降至23毫秒**[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值