sql优化
本文最后更新于:2025年5月25日 晚上
SQL优化
一、SQL执行频率
1、查看当前会话的 SQL 命令执行统计信息
1 |
|
2、慢查询日志
慢查询日志(slow_query_log
)可以记录执行时间超过指定阈值的 SQL 语句。通过分析慢查询日志,可以间接了解 SQL 的执行频率。
步骤:
-
启用慢查询日志:
1
2SQLSET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 设置慢查询阈值(单位:秒) -
查看慢查询日志文件路径:
1
SHOW VARIABLES LIKE 'slow_query_log_file';
-
分析慢查询日志文件,查看 SQL 执行频率。
1
2show variables like 'long_query_time%' -- 查看慢日志记录sql的最低阈值时间
set global long_query_time = 4; -- 设置最低时间 -
定位低效率执行SQL
1
show processlist;
执行结果:
Id User Host db Command Time State Info 5 event_scheduler localhost null Daemon 2550 Waiting on empty queue null 8 root 172.17.0.1:54214 Scores Query 0 init show processlist 各列含义:
-
Id列,用户登录mysql时,系统分配的connection_id,可以使用函数connection_id来查看。
-
User列,显示当前用户。如果不是root,这个命令就只显示用户权限范围的SQL语句
-
Host列,显示这个语句是从哪个ip和端口上发的,可以用来跟踪出现问题语句的用户
-
db列,显示这个进程目前连接的是哪个数据库
-
Commandl列,显示当前连接的执行的命令,一般取值为休眠(Sleep),查询(Query),连接(connent)等.
-
Time列,显示这个状态持续的时间,单位(秒)
-
State列,显示使用当前连接的sql语句的状态,很重要的列。state描述的是语句中的某一个状态。一个sql语句,以查询为例,可能需要经过copying to tmp table,sorting result,sending data等状态才可以完成
-
info列,显示这个sql语句,是判断问题语句的一个重要依据。
-
二、Explain分析执行计划
基本使用
句式:
1 |
|
示例:
1 |
|
结果:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | user | ALL | 6 | 100.00 | Using filesort |
列表含义:
字段 | 含义 |
---|---|
Id | select查询的序列号,是一组数字,表示查询中执行select子句或者操作表的顺序 |
select_type | select类型,常见的取值SIMPLE(简单表,不使用表连接或子查询),PRIMARY(主查询,即外层的查询),UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个SELECT)等 |
table | 输出结果集的表 |
partitions | 显示查询将访问哪些分区(如果表使用了分区)。【分区的介绍和用法将单独写一篇文章】 |
type | 表示表的连接类型,性能由好到差的连接类型为(system >> const >> eq_ref >> ref >> ref_or_null >> index_merge >> index_subquery >> range >> index >> all)mysql5.7及以上对系统查表,返回的是all,而不是system |
possible_keys | 表示查询时,可能使用的索引 |
key | 表示实际使用的索引 |
key_len | 索引字段的长度 |
ref | 显示在连接条件或索引查找中,哪些列或常量被用于与索引进行比较。 |
rows | 扫描行的数量 |
filtered | 显示查询优化器估算的、经过条件过滤后剩余的行数占扫描行数的百分比。 范围是 0 到 100 。 100 表示没有进行过滤。 |
Extra | 执行情况的说明和描述 |
三、Show profile分析sql
MySQL5.0.37开始增加对show profiles
和 show profile
语句的支持。
这能帮助我们时间耗费到哪里去了。
1 |
|
四、Trace分析优化器执行计划
1 |
|
完整过程:
1 |
|
输出内容
- QUERY: 被跟踪的查询。
- TRACE: 优化器的详细决策过程,包括解析、优化和执行阶段。
- MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 如果跟踪信息超出最大内存限制,显示缺失的字节数。
- INSUFFICIENT_PRIVILEGES: 是否有权限不足的问题。
五、索引优化
索引生效会使得执行效率提高!
1 |
|
其他匹配原则
1 |
|
以上都加了explain 在查询效率的结果中,Extra列:
- using index:使用覆盖索引会出现
- using where :使用索引时需要回表查询时会出现
- using index condition:使用索引时需要回表查询时会出现
- using index; using where: 使用索引时,数据都能在索引中找到,不需要回表查询时会出现
六、SQL优化
大批量数据加载优化
6.1、主键顺序插入
检查全局系统变量local_infile
的状态
1 |
|
加载数据
通过load向表加载数据时,保证文件中数据主键有序可提高效率!
1 |
|
6.2、关闭唯一性校验
这里是当表中存在UNIQUE约束时,大批量加载数据会每次都进行唯一性校验,这将显著降低加载效率!
通常插入的这种大批量的表是不需要再校验的,所以需要关闭后再加载,之后再开启就好了。
1 |
|
优化insert
语句
多值表的insert语句
1 |
|
手动事务提交
1 |
|
插入的数据尽量有序,避免无序
1 |
|
优化 order by
语句
两种排序方式
filesort:非索引排序就是filesort
index:用索引排序
1 |
|
FileSort优化
两次扫描算法:mysql4.1之前,使用该方式排序。首先取出排序字段和行指针信息,然后在排序区sort buff 中排序,如果sort buff不够,则在临时表中存储排序结果。完成排序后再回表读取记录,期间会导致大量随机I/O操作。
**一次扫描算法:**一次性取出满足条件的所有字段,然后在排序区排序后直接输出结果集。此方法在排序时内存开销大,但是效率比两次扫描高。
mysql通过系统变量max_length_for_sort_data
的大小和Query语句取出字段总大小,来判定用哪种算法。如果系统变量max_length_for_sort_data
更大,则用第二种,否则用第一种。
可以适当提高sort_buffer_size
和max_length_for_sort_data
系统变量,来增大排序区的大小,提高排序效率。
1 |
|
优化子查询
能用连接查询就尽量不要用子查询,子查询需要建立临时表后再进行查询,这两步操作会使得效率低于连接查询。
Limit优化
优化思路一
在索引上完成排序分页的操作,最后根据主键关联回原表查询所需要的其他列内容
1 |
|
优化思路二
适用于主键自增的表,可以把limit查询转换成某个位置的查询。
1 |
|