4.SQL 性能分析笔记
在 MySQL 中进行性能分析是数据库优化的重要一环。通过识别性能瓶颈,优化 SQL 查询和数据库配置,可以显著提高应用的响应速度和吞吐量。以下是 MySQL 性能分析的进阶笔记,涵盖了常见的性能分析方法和工具。
1. 查询缓存(Query Cache)
MySQL 提供了查询缓存(query_cache),缓存已经执行过的查询结果,以提高后续相同查询的执行速度。但它的使用效果在高并发的情况下可能会降低性能,从 MySQL 5.7.20 开始, 查询缓存已经被废弃。
启用查询缓存:
            
            
              sql
              
              
            
          
          SET GLOBAL query_cache_type = 1;
SET GLOBAL query_cache_size = 1048576;  -- 1MB 缓存注意事项:
- 查询缓存对于 INSERT、UPDATE、DELETE等修改数据的操作没有太大作用,反而可能增加性能开销。
- 查询缓存适合读取频繁但变化较少的场景。
2. EXPLAIN 分析查询执行计划
EXPLAIN 是分析 SQL 查询执行计划的一个常用工具,它帮助我们了解 MySQL 如何执行查询,包括使用哪些索引、如何扫描数据等。其基本用法如下:
            
            
              sql
              
              
            
          
          EXPLAIN SELECT * FROM users WHERE age > 25;EXPLAIN 输出解释:
| 字段 | 含义 | 
|---|---|
| id | 查询的标识符,标识不同的查询步骤 | 
| select_type | 查询类型,例如:SIMPLE(简单查询)、PRIMARY(最外层查询)、SUBQUERY(子查询)等 | 
| table | 表名,表示该步骤操作的表 | 
| type | 连接类型,表示 MySQL 如何查找数据,性能由 type的值决定,常见的有:ALL(全表扫描)、index(索引扫描)、range(范围扫描)、ref(使用索引进行查找)、const(常数查询)等 | 
| possible_keys | 可能使用的索引 | 
| key | 实际使用的索引 | 
| key_len | 使用的索引长度 | 
| ref | 表示索引是如何与其他表的字段进行连接的 | 
| rows | 扫描的行数估计值 | 
| Extra | 额外信息,表示查询执行的附加信息,如 Using where、Using index等 | 
优化建议:
- 如果 type为ALL,意味着查询使用了全表扫描,可以考虑添加合适的索引来优化。
- 如果 rows数量很大,可能需要进一步检查查询条件和表结构。
- 关注 Extra字段,查看是否存在全表扫描、临时表等性能瓶颈。
3. 慢查询日志
MySQL 提供了慢查询日志(slow_query_log),记录所有执行时间超过指定阈值的查询。启用慢查询日志后,可以分析慢查询并优化。
启用慢查询日志:
            
            
              sql
              
              
            
          
          SET GLOBAL slow_query_log = 1;
SET GLOBAL slow_query_log_file = '/path/to/slow-query.log';
SET GLOBAL long_query_time = 2;  -- 查询时间大于1秒的都会被记录分析慢查询日志:
通过 mysqldumpslow 或 pt-query-digest 等工具分析慢查询日志,找出哪些查询执行时间过长、哪些查询需要优化。
3. 查看 SQL 执行频次
通过执行 SHOW GLOBAL STATUS LIKE 'Com%' 命令,可以查看 MySQL 系统中所有执行过的 SQL 命令的频次统计。这些统计数据可以帮助我们了解哪些 SQL 操作在系统中最为频繁,并根据执行频次来判断是否需要优化某些查询或操作。
常见的 Com% 状态变量:
- Com_select :执行 SELECT查询的次数
- Com_insert :执行 INSERT查询的次数
- Com_update :执行 UPDATE查询的次数
- Com_delete :执行 DELETE查询的次数
- Com_create_table:创建表的次数
- Com_drop_table:删除表的次数
- Com_commit:事务提交的次数
- Com_rollback:事务回滚的次数
通过查看这些统计信息,您可以识别出哪些操作是系统中频繁执行的。例如,如果 Com_select 的值异常高,而其他如 Com_insert 或 Com_update 的值较低,这可能意味着查询操作频繁,而数据修改较少,您可以从查询优化方面入手。
示例:
            
            
              sql
              
              
            
          
          SHOW GLOBAL STATUS LIKE 'Com%';输出示例:
            
            
              sql
              
              
            
          
          +------------------------+---------+
| Variable_name          | Value   |
+------------------------+---------+
| Com_select             | 150000  |
| Com_insert             | 50000   |
| Com_update             | 20000   |
| Com_delete             | 10000   |
| Com_create_table       | 5       |
| Com_drop_table         | 3       |
+------------------------+---------+通过分析这些数据,您可以看到最频繁的操作类型,从而做针对性的优化。
4. 查询性能分析
SHOW PROFILES 命令用于查看 SQL 查询的执行性能,可以帮助开发人员查看查询执行的各个阶段耗时,进一步发现查询性能瓶颈。SHOW PROFILES 返回的是在当前会话中执行过的所有 SQL 查询的时间统计信息,包括每个查询的总执行时间、各个阶段的时间消耗等。
启用 profiling 功能:
在 MySQL 5.0 及以上版本中,profiling 默认是禁用的。如果需要使用该功能,您需要先通过以下命令启用它:
            
            
              sql
              
              
            
          
          SET profiling = 1;使用 SHOW PROFILES 查询执行时间:
执行完查询后,可以使用 SHOW PROFILES 来查看执行过的 SQL 语句以及各个阶段的执行时间。
            
            
              sql
              
              
            
          
          SHOW PROFILES;输出示例:
            
            
              sql
              
              
            
          
          +------+------------------------------------------+-----------+
| Query_ID | Query                                  | Duration  |
+---------+----------------------------------------+-----------+
| 1       | SELECT * FROM users WHERE age > 25     | 0.002300  |
| 2       | SELECT * FROM orders WHERE order_id=123| 0.001500  |
+---------+----------------------------------------+-----------+- Query_ID: 查询的唯一标识符
- Query: 执行的 SQL 查询
- Duration: 执行时间(秒)
查看查询执行的详细阶段:
通过 SHOW PROFILE FOR QUERY <query_id> 可以查看指定查询的详细执行阶段信息,如解析、优化、执行等各个阶段的耗时。
            
            
              sql
              
              
            
          
          SHOW PROFILE FOR QUERY 1;输出示例:
            
            
              sql
              
              
            
          
          +--------------------------+----------+
| Status                   | Duration |
+--------------------------+----------+
| starting                 | 0.000030 |
| reading from net         | 0.000340 |
| preparing                | 0.000020 |
| executing                | 0.000250 |
| sending data             | 0.000180 |
| end                      | 0.000010 |
| query end                | 0.000080 |
| closing tables           | 0.000060 |
| freeing items            | 0.000020 |
| cleaning up              | 0.000010 |
+--------------------------+----------+字段解释:
- Status : 查询的执行状态(例如 starting、executing、sending data等)
- Duration: 每个阶段的执行时间,单位是秒
通过分析这些阶段的耗时,您可以找出查询中最耗时的部分,并做针对性的优化。例如,如果 reading from net 阶段耗时较长,可能是因为网络延迟或查询结果集过大;如果 sending data 阶段耗时较长,可能是因为 MySQL 在处理大量数据。
总结
MySQL 性能优化是一个不断调优的过程,从硬件配置到查询结构优化再到索引设计,都需要全面考虑。利用 EXPLAIN 分析执行计划、慢查询日志、索引优化、内存调优等手段,可以有效提升数据库的性能。在高并发、大数据量的场景下,分库分表、查询缓存、连接优化等技术也是不可或缺的工具。