SQL 分析基本操作
① 观察一天查看生产环境 SQL 慢的情况;
② 开启慢查询日志,设置阈值,如超过 5s 的就是慢查询,并抓取 SQL;
③ 使用 EXPLAIN + SQL 语句
查看慢SQL;
④ 使用 show profile
进行进一步分析;
⑤ 运维或DBA 进行 SQL 服务器参数调优;
小表驱动大表
使用小表驱动大表,类似于多层循环,最外层最好循环次数要少,否则会消耗很长时间。同理当 MySQL 进行 CRUD 操作时会进行锁表操作时应当使用小的结果集驱动大的结果集。
select * from A where id in (select id from B) 等价于
for select id from B
for select * from A where A.id = B.id
当 B表的数据集必须小于 A表的数据集时,使用
in
优于exists
select * from A where exists (select 1 from B where B.id = A.id) 等价于
for select * from A
for select * from B where B.id = A.id
当 A表数据集小于 B表数据集时,使用
exists
优于in
exists
语法 select... from table where exists (subquery)
可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE、FALSE)来决定结果是否保留。
exists(subquery)
只返回TRUE、FALSE
,因此子查询中的条件字段可以是SELECT 1
或SELECT X
,官方的解释是在实际执行时会忽略SELECT
清单,因此没有区别;
exists
子查询的实际执行过程可能经过了优化而不是逐条对比;
exists
子查询也可以使用条件表达式、其他子查询或者JOIN
来替代,需要根据具体问题具体分析;
1. 查询优化
1.1 关联查询优化
1.1.1 左/右连接
① 优化关联查询时需要在被驱动表上建立索引才能提高性能;
② 尽可能减少 Join
语句中的 NestedLoop
的循环次数;“用小结果集驱动大结果集”
③ 优先优化 NestedLoop
的内层字段;
④ 当无法保证驱动表的 JOIN
字段被索引且内存充足的条件下,可以适当调整 JoinBuffer
设置;
驱动表和被驱动表:
LEFT JOIN
查询时,左侧的表为驱动表右侧的表为被驱动表;
RIGHT JOIN
查询时,右侧的表为驱动表左侧的表为被驱动表;
**示例:**在 book
表的 card
列建立单值索引
通过上面的 SQL 查询可以看出建立在
book
表的card
列的单值索引,在右连接作为驱动表时被使用,将查询的列从 40 条降低到1条。
1.1.2 内关联
在使用 INNER JOIN
时 MySQL 会自动将小结果集的表作为驱动表;
STRSAIGHT_JOIN
效果和 INNER JOIN
一样,但是会强制将左侧作为驱动表
**示例:**在 book
表的 card
列建立单值索引
通过上面的 SQL 可以看到 MySQL 对于
inner join
会自动选择结果集小的表作为驱动表,左右表无论那个建立索引都会被使用。
通过上面 SQL 可以看到,
straight_join
会强制将左侧的表作为驱动表,会导致建立索引的表失效。
1.1.3 多表嵌套关联
子查询尽量不要放在被驱动表,有可能不能使用索引;
LEFT JOIN
时尽量让实体表作为被驱动表;
1.2 子查询优化
在进行范围判断时,尽量不要使用 NOT IN
和 NOT EXISTS
,使用 LEFT JOIN ON XXXX IS NULL
代替。
1.3 排序分组优化
order by
子句尽量使用 index
方式排序,避免使用 filesort
方式进行排序。
① 建立数据库表
# 建立数据库表
create table tblA(
#id int primary key not null auto_increment,
age int,
birth timestamp not null
);
insert into tblA(age, birth) values(22, now());
insert into tblA(age, birth) values(23, now());
insert into tblA(age, birth) values(24, now());
# 在 tablA 表建立复合索引
create index idx_A_ageBirth on tblA(age, birth);
# 查询数据表
mysql> select * from tblA;
+------+---------------------+
| age | birth |
+------+---------------------+
| 22 | 2021-04-19 10:04:26 |
| 23 | 2021-04-19 10:04:26 |
| 24 | 2021-04-19 10:04:29 |
+------+---------------------+
3 rows in set (0.00 sec)
# 查询索引
mysql> show index from tblA;
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tbla | 1 | idx_A_ageBirth | 1 | age | A | 3 | NULL | NULL | YES | BTREE | | |
| tbla | 1 | idx_A_ageBirth | 2 | birth | A | 3 | NULL | NULL | | BTREE | | |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.01 sec)
② 分析 SQL 查询
1)范围后排序
索引顺序和查询使用顺序保持一致,遵循最佳左前缀法则,使用了索引,且使用了覆盖索引。
索引顺序和查询使用顺序保持一致,遵循最佳左前缀法则,使用了索引,且使用了覆盖索引。
age
字段进行了范围查询,导致索引失效,转而进行了文件排序,性能开销较大。
2)直接排序(ORDER BY 默认为升序)
索引为复合索引,但是
age
没有被使用,而是直接使用birth
进行排序,所以使用了文件排序。
使用了覆盖索引,索引列
age
参与排序,索引列birth
参与条件查询
③ 总结
MySQL 支持两种排序方式,index
和 filesort
,index
的效率更高,它使用 MySQL 扫描索引完成排序,filesort
的效率比较低,它在进行文件排序会进行大量的 IO 操作严重影响数据库性能。
ORDER BY
满足两种情况时,会使用 index
方式进行排序:
ORDER BY
语句使用索引最左前列;- 使用
WHERE
子句与ORDER BY
子句条件列满足索引最左前列;
建议:尽可能在索引列上完成排序操作,遵循最佳左前缀法则
ORDER BY
能使用索引的情况:①
ORDER BY
能使用索引的最左前缀;②
WHERE
使用索引的最左前缀定义为常量,此时ORDER BY
能使用索引;
ORDER BY
不能使用索引的情况:① 排序不一致的时候;
② 不满足最佳左前缀法则(带头大哥不能死,中间兄弟不能断)
③
ORDER BY
后面的某个字段不是索引列;④
WHERE
条件中使用IN
,对于排序而言多个相等条件等同于范围查询;
1.3.1 无过滤不索引
where
和 limit
都相当于一种过滤条件,所以才能使用索引。
索引为复合索引,但是
age
没有被使用,而是直接使用birth
进行排序,所以使用了文件排序。
1.3.2 顺序错必排序
ORDER BY
后面的字段顺序不可以随意调整,会导致索引失效。
复合索引的建立顺序是
age
和birth
但是在ORDER BY
时复合索引建立的顺序被破坏,导致 MySQL 进行了文件排序,数据库性能开销较大。
1.3.3 方向反必排序
就是前一个字段使用正序排序,后一个字段使用倒序排序。如果排序的字段,顺序存在差异,就需要将差异的部分进行倒置排序,因此还是需要手动排序。
age
字段排序为ASC
升序排序,birth
字段为DESC
降序排序,需要对原先排序好的数据进行倒置,导致使用文件排序。
1.3.4 索引的选择
两个索引同时存在时,MySQL 选择的索引。
所有的排序都是在条件过滤后才执行的,所以如果条件过滤掉大部分数据的话,千百条数据进行排序的性能开销并不是很大,即使使用索引进行优化排序对实际的性能提升也是有有限的。使用范围查询过滤掉大部分数据和对几万条数进行排序相比,在范围排序中使用索引后对服务器性能开销更小。
当范围条件和
GROUP BY
或ORDER BY
的字段出现二选一时, 优先观察条件字段的过滤数量,如果过滤的数据足够多,而需要排序的数据不多时,优先在范围字段上加索引。反之同样操作。
1.3.5 使用覆盖索引
覆盖索引可以解决使用 LIKE
进行模糊查询时造成的索引失效问题;
覆盖索引也可以解决使用 !=、<>
导致的索引失效问题;
覆盖索引:SQL 只需要通过索引就可以查询到所需的数据,而不不需要通过二级索引查询到主键后再查询数据。
1.3.6 文件排序详解
MySQL 中的文件排序算法
双路排序算法:
也就是进行两次磁盘扫描,最终得到数据,读取行指针和 ORDER BY
列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出。从磁盘取排序字段,在 buffer
中进行排序再从磁盘取出其他字段。
单路排序算法:
从磁盘读取查询需要的所有列,按照 OREDER BY
列在 buffer
对他们进行排序,然后扫描排序后的列表进行输出效率相比双路排序会更快一些,避免额数据的二次读取。将随机 IO 变为顺序 IO,但是需要使用更多的空间
单路排序算法存在的问题:
在
sort_buffer
中,单路排序算法比双路排序算法需要占用更多的空间,因为单路排序算法将所有字段全部取出,所以有可能导致取出的数据总大小超出了sort_buffer
的容量,导致每次只能取出sort_buffer
容量大小的数据进行排序(创建 tmp 文件,进行多路合并)排完后再取出sort_buffer
容量大小的数据,再进行排序,从而导致进行了多次 IO 操作。
如何优化 MySQL 配置
① 增加 sort_buffer_size
参数设置
无论采用哪种算法,提高 sort_buffer_size
参数都会提高效率,可以根据系统情况进行适当的调整,建议 “1M-8M” 之间。
② 增大 max_length_for_data
参数设置
MySQL 使用单路排序的前提是排序的字段大小要小于 max_length_for_data
,提高这个参数可以增加使用单路排序算法的概率。但是如果设置的过高,数据总容量超出 sort_buffer_size
的概率会增加,造成很高的磁盘 IO 操作和很低的处理器使用率。建议在**“1024-8192”**之间调整
③ 减少 select
后面的查询字段,最好不要用 select *
当 query
的字段大小总和小于 max_length_sort_data
且排序字段不是 TEXT|BLOB
类型时,会使用单路排序算法,否则使用双路排序算法。
两种排序算法的数据都有可能超出 sort_buffer
的容量,超出后会创建 tmp 文件进行合并排序,导致多次 IO,但是使用单路排序算法的风险会大一些,因此要提高 sort_buffer_size
.
1.3.7 分组优化
分组的前提是排序,因此 GROUP BY
使用索引的原则几乎和 ORDER BY
使用索引的原则一致,唯一的区别是 GROUP BY
中即使没有过滤条件用到索引,也可以直接使用索引。
WHERE
的效率高于HAVING
,能在WHERE
中过滤掉的条件没有必要在HAVING
中进行限定。
2. 慢查询日志
2.1 慢查询日志介绍
MySQL 的慢查询日志是 MySQL 提供的一种日志记录,用来记录在 MySQL 中响应时间超过阈值的语句,具体指运行时间超过 long_query_time
值的 SQL,会被记录到慢查询日志中。long_query_time
值的默认值是10s,也就是运行时间超过 10s 的 SQL 会被记录到慢查询日志中。通过慢查询日志可以帮助我们定位到存在问题的 SQL,结合 EXPLAIN
对 SQL 语句进行分析优化。
2.2 使用慢查询日志
MySQL 默认情况下是没有开启慢查询日志的,需要手动设置参数。如果不需要进行 SQL 调优的话不建议开启此参数,因为慢查询日志会影响性能,慢查询日志支持将日志记录写入文件。
开启慢查询日志
① 查看慢查询日志是否开启:
mysql> SHOW VARIABLES LIKE '%slow_query_log%';
+---------------------+-------------------------------------------------+
| Variable_name | Value |
+---------------------+-------------------------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/izuf6h7blj36dmxbmcj15wz-slow.log |
+---------------------+-------------------------------------------------+
2 rows in set (0.00 sec)
参数说明:
- 默认情况下
slow_query_log
的值为OFF
,即慢查询日志是禁用的。- 关于慢查询参数
slow_query_log_file
,它是指定慢查询日志文件的存放路径,系统会默认给一个缺省的文件host_name-slow.log
(如果没有指定参数slow_query_log_file
的话)Tips:MySQL 为了保证性能大多数的功能都是禁用的
② 开启慢查询日志:
set global slow_query_log=1;
使用此命令仅对当前数据库生效,如果 MySQL 重启则会失效,即慢查询日志功能再次关闭。
③ 查看慢查询设定的查询阈值:
mysql> show variables like 'long_query_time%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
单位秒
假如运行时间正好等于
long_query_time
的情况,并不会被记录下来,也就是说只有查询的 SQL 的时间大于设定的阈值才会被记录。
③ 设定慢查询阈值:
set long_query_time = xxxx
# 查看默认设置的慢查询阈值时间
mysql> show variables like '%long_query_time%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
# 设定慢查询的阈值时间
mysql> set long_query_time = 3;
Query OK, 0 rows affected (0.00 sec)
# 查看设置后的慢查询阈值时间
mysql> show variables like '%long_query_time%';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 3.000000 |
+-----------------+----------+
1 row in set (0.00 sec)
也可以通过向
my.cnf
文件中添加参数来修改;设置后查询发现设定的时间没有生效的原因:
- 重新连接或打开新的会话才能看到修改后的值,命令:
show variables like 'long_query_time%';
- 或者使用新的命令查看
show global variables like 'long_query_time%';
④ 查询当前系统中有多少条慢查询记录
show global status like '%slow_queries%'
mysql> show global status like '%slow_queries%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries | 2 |
+---------------+-------+
1 row in set (0.00 sec)
⑤ 通过修改配置文件实现永久修改
my.cnf
文件中找到下面的位置复制以下代码,根据自己的实际情况配置参数和日志输出位置。
[mysqld]
slow_query_log=1
slow_query_log_file=/var/lib/mysql/xxx-slow.log
long_query_time=3
log_output=FILE
配置详解:
slow_query_log
:开启/关闭慢查询日志;
slow_query_log_file
:慢查询日志文件输出位置和名称;
long_query_time
:慢查询 SQL 时间阈值;
log_output
:慢查询日志输出格式:
- 可以是
FILE
(存储在数据库的数据文件中的host_name.log
文件)- 也可以是
TABLE
(存储在数据库中的mysql.general_log
)
2.3 日志分析工具
在生产环境中,如果要手工分析日志,查找、分析 SQL,会很浪费时间,MySQL 提供了日志分析工具 mysqldumpslow
mysqldumpslow
帮助信息详解
参数 | 含义 |
---|---|
s | 表示按照何种方式进行排序 |
c | 访问次数 |
l | 锁定时间 |
r | 返回记录 |
t | 查询时间 |
al | 平均锁定时间 |
ar | 平均返回记录数 |
at | 平均查询时间 |
t | 返回前面多少条数据 |
g | 后面搭配一个正则匹配模式,大小写不敏感 |
MySQL 进程查看工具
SHOW PROCESS
查询 MySQL 进程列表,杀掉故障进程回收资源。
查看日志:
① 获取返回记录集中最多的 10 个 SQL
mysqldumpslow -s r -t 10 /var/lib/mysql/test-slow.log
② 获取访问次数最多的 10 个 SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/test-slow.log
③ 获取按照时间排序的前 10 条包含左连接的查询语句
mysqldumpslow -s t 10 -g "left join" /var/lib/mysql/test-slow.log
④ 建议在执行以上命令时结合 | more
使用,防止打印的数据过长
mysqldumpslow -s r -t 10 /var/lib/test-slow.log | more
3. 批量数据脚本
总结 SQL 创建各种
创建表:
create table
创建索引:
create index
创建函数:
create function
创建视图:
create view
建立两张数据库表并插入 50w 条数据进行压力测试
3.1 建立数据库表
创建 dept
表和 emp
表
CREATE TABLE `dept` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`deptName` VARCHAR(30) DEFAULT NULL,
`address` VARCHAR(40) DEFAULT NULL,
ceo INT NULL ,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
# 1.1创建员工表
CREATE TABLE `emp` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`empno` INT NOT NULL ,
`name` VARCHAR(20) DEFAULT NULL,
`age` INT(3) DEFAULT NULL,
`deptId` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
3.2 配置数据库参数
查看参数是否开启 show variables like 'log_bin_trust_function_creators';
打开参数 set global log_bin_trust_function_creators = 1
# 查看参数是否开启
mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | OFF |
+---------------------------------+-------+
1 row in set (0.00 sec)
# 开启参数
mysql> set global log_bin_trust_function_creators = 1;
Query OK, 0 rows affected (0.00 sec)
# 再次查看参数是否开启
mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | ON |
+---------------------------------+-------+
1 row in set (0.00 sec)
当二进制日志启用后,这个变量就会启用,这个变量是控制 MySQL 是否信任存储函数的创建者,不会创建写入二进制日志引起不安全事件的存储函数。参数默认设置为
OFF
,用户不得创建或修改存储函数,除非操作用户具有除去CREATE ROUTINE
或ALTER ROUTINE
特权之外的SUPER
权限。设置为OFF
还强制使用DETERMINISTIC
特性或READS SQL DATA
或NO SQL
特性声明函数的限制。 如果变量设置为ON
,MySQL 不会对创建存储函数实施这些限制。 此变量也适用于触发器的创建。当我们开启二进制日志后,如果变量
log_bin_trust_function_creators
的设置为OFF
,则在创建存储函数时会报错ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
3.3 创建函数
① 随机产生字符串
DELIMITER $$
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END $$
DELIMITER
:设置结束字符。MySQL 默认的结束字符是;
但是在编写函数时会使用到,避免函数无法完全被执行,将结束符号替换为$$
② 随机产生编号
DELIMITER $$
CREATE FUNCTION rand_num (from_num INT ,to_num INT) RETURNS INT(11)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(from_num +RAND()*(to_num -from_num+1)) ;
RETURN i;
END$$
③ 删除函数
# 删除随机产生字符串的函数
drop function rand_string
# 删除随机产生编号的函数
drop function rand_num;
3.4 创建存储过程
① 创建向 emp
表中插入数据的存储过程
DELIMITER $$
CREATE PROCEDURE insert_emp( START INT , max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
#set autocommit =0 把autocommit 设置成0
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO emp (empno, NAME ,age ,deptid ) VALUES ((START+i) ,rand_string(6) ,
rand_num(30,50),rand_num(1,10000));
UNTIL i = max_num
END REPEAT;
COMMIT;
END$$
② 创建向 dept
表中插入数据的存储过程
DELIMITER $$
CREATE PROCEDURE `insert_dept`( max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO dept ( deptname,address,ceo ) VALUES (rand_string(8),rand_string(10),rand_num(1,500000));
UNTIL i = max_num
END REPEAT;
COMMIT;
END$$
3.5 调用存储过程
① 调用存储过程向 dept
表插入 1w 条数据
DELIMITER ;
CALL insert_dept(10000);
② 调用存储过程向 emp
表插入 50w 条数据
DELIMITER ;
CALL insert_emp(100000,500000);
4. Show profile
SQL 查询问题排查基本步骤:
① 监控系统中收到当前系统中的 SQL 异常信息;
② 打开慢查询日志,抓取存在问题的 SQL ;
③ 对存在问题的 SQL 使用 EXPLAIN
关键字进行 SQL 分析;
④ 使用 show profile 继续排查 SQL 问题;
⑤ 调整 MySQL 的参数配置;
4.1 Show profile 介绍
是 MySQL 提供的可用于分析当前会话中语句执行的资源消耗情况。可以用于 SQL 的调优测量工具,默认情况下参数处于关闭状态,并保存最近 15 次的运行结果。可以使用 show profile 查看 SQL 的执行周期。
4.2 分析步骤
① 查看是否开启
show variables like '%profiling%'
② 开启功能
set profiling = 1
③ 运行 SQL 语句
④ 查看运行结果
查看全部查询记录:show profiles
mysql> show profiles;
+----------+------------+----------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+----------------------------------------------------------+
| 1 | 0.00040950 | show variables like '%profiling%' |
| 2 | 0.00006050 | show profies |
| 3 | 0.00008050 | select * from tbl_emp |
| 4 | 0.12290000 | select * from emp group by id limit 150000 |
| 5 | 1.03373300 | select * from emp left join dept on emp.deptid = dept.id |
+----------+------------+----------------------------------------------------------+
5 rows in set (0.00 sec)
查看具体的某条查询记录:show profile cpu,block io for query Query_id
status 参数信息
参数 | 含义 |
---|---|
ALL | 显示所有的开销信息 |
BLOCK IO | 显示块 IO 相关开销信息 |
CONTEXT SWITCHES | 显示上下文切换相关开销信息 |
CPU | 显示 CPU 相关开销信息 |
IPC | 显示发送和接收相关开销信息 |
MEMORY | 显示内存相关开销信息 |
PAGE FAULTS | 显示页面错误相关开销信息 |
SOURCE | 显示和 Source_function,Source_file,Source_file 相关开销信息 |
SWAPS | 显示交换次数相关开销信息 |
⑤ 诊断 SQL
通过查看 SQL 语句运行时资源的消耗情况,结合 EXPLAIN
语句分析 SQL 中存在的问题对 SQL 进行优化。
4.3 总结
status 中出现以下语句则表示 SQL 存在问题需要优化:
① converting HEAP to MyISAM
查询结果过大,内存不够用转而存储到硬盘;
② Create tmp table
创建临时表,主要作用:拷贝数据到临时表,使用完成后删除临时表;
③ Copy to tmp table on disk
将内存中临时表复制到磁盘,严重影响性能;
④ locked
锁;
5. 全局慢查询
5.1 配置启用
在my.cnf
文件中找到下面的部分,放到对应位置
[mysqld]
# 开启
general_log=1
# 记录日志文件路径
general_log_file=/path/logfile
# 输出格式
log_output=FILE
5.2 编码启用
① 开启全局慢查询
set global_log=1;
set global_log_output='table';
② 查看所有的查询记录
开启后所编写的 SQL 语句,将会记录到 MySQL 库中的 general_log
表
使用命令 select * from mysql.general_log
查看
注意事项:不要在生产环境开启慢查询日志,会消耗资源导致性能下降影响系统运行。