本篇文章主要是对MySQL学习时的一些总结,作为学习笔记记录
查看是否开启及如何开启
# 查看参数设置,默认为OFF,表示禁用
SHOW VARIABLES LIKE '%slow_query_log%';
# 开启慢查询日志
SET GLOBAL slow_query_log = 1;
开启慢查询日志后,什么样的sql语句才会被记录到慢查询日志当中呢?这个可以查看long_query_time变量:
该值可以通过命令修改,也可以在my.cnf配置文件中修改。
在my.cnf配置文件中配置为:
# [mysqld]
slow_query_log=1;
slow_query_log_file=/var/lib/mysql/atguigu-slow.log
long_query_time=3;
log_output=FILE
通过命令行修改为:
修改后发现并没有什么变化,这是因为需要重新连接或者新开一个会话才能看到修改后的值,重新打开一个新的会话查看参数:
也可以通过修改会话变量进行设定:
但是如果运行时间正好等于long_query_time的情况,并不会被记录下来。也就是说,在mysql源码里是判断大于long_query_time,而非大于等于。
产生一条慢sql
对应的慢查询日志中的内容为:
查看当前系统中有多少条慢查询记录
SHOW GLOBAL STATUS LIKE 'Slow_queries';
mysqldumpslow提供了对慢查询日志文件的分析。
帮助信息
‘mysqldumpslow的帮助信息为:
各参数的含义为:
工作常用参考
# 得到返回记录集最多的10个SQL
mysqldumpslow -s r -t 10 /usr/local/mysql/data/sakura-mysql-slow.log
# 得到访问次数最多的10个SQL
mysqldumpslow -s c -t 10 /usr/local/mysql/data/sakura-mysql-slow.log
# 得到按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" /usr/local/mysql/data/sakura-mysql-slow.log
# 另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现爆屏情况
mysqldumpslow -s r -t 10 /usr/local/mysql/data/sakura-mysql-slow.log | more
往表中插入1000W条数据
建表
# 新建库
CREATE DATABASE bigData;
USE bigData;
#1 建表dept
CREATE TABLE dept (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR (20) NOT NULL DEFAULT "",
loc VARCHAR (13) NOT NULL DEFAULT ""
) ENGINE = INNODB DEFAULT CHARSET = UTF8 ;
#2 建表emp
CREATE TABLE emp (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
ename VARCHAR (20) NOT NULL DEFAULT "",
job VARCHAR (9) NOT NULL DEFAULT "",
mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
hiredate DATE NOT NULL,
sal DECIMAL (7, 2) NOT NULL,
comm DECIMAL (7, 2) NOT NULL,
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0
) ENGINE = INNODB DEFAULT CHARSET = UTF8 ;
创建函数
随机产生字符串:
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 $$
CREATE FUNCTION rand_num( ) RETURNS INT(5)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(100+RAND()*10);
RETURN i;
END $$
如果出现下述的错误:
则需要首先执行下述语句:
SHOW VARIABLES LIKE 'log_bin_trust_function_creators';
SET GLOBAL log_bin_trust_function_creators=1;
创建存储过程
创建往emp表中插入数据的存储过程:
DELIMITER $$
CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO emp (empno, ename ,job ,mgr ,hiredate ,sal ,comm ,deptno ) VALUES ((START+i) ,rand_string(6),'SALESMAN',0001,CURDATE(),FLOOR(1+RAND()*20000),FLOOR(1+RAND()*1000),rand_num());
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
创建往dept表中插入数据的存储过程:
DELIMITER $$
CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO dept (deptno ,dname,loc ) VALUES (START +i ,rand_string(10),rand_string(8));
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
调用存储过程
dept:
DELIMITER ;
CALL insert_dept(100,10);
emp:
#执行存储过程,往emp表添加50万条数据
DELIMITER ;
CALL insert_emp(100001,500000);
大量数据案例
emp表结构为:
执行explain分析:
从上图的结果来看,type的类型为all,extra中出现了filesort,因此需要优化。
尝试建立组合索引:
CREATE INDEX idx_dno_eno_ena ON emp(deptno,empno,ename);
进行explain分析:
从上述结果看出,filesort仍然存在,因此ename并没有用到索引(empno是一个范围,empno之后的字段不会用到索引),还需要继续进行优化。
删除索引并建立新的索引:
DROP INDEX idx_dno_eno_ena ON emp;
CREATE INDEX idx_dno_ena ON emp(deptno,ename);
进行explain分析:
从上面的结果可以看出,type的类型变为了ref,filesort消失了,
而如果建立idx_dno_eno索引是什么情况呢?
DROP INDEX idx_dno_ena ON emp;
CREATE INDEX idx_dno_eno ON emp(deptno,empno);
从上面的结果可以看出,仍然存在filesort,这意味着排序没有使用到索引。
但对比运行速度来看,存在filesort的sql运行速度超过了已经优化掉filesort的sql,这是什么原因?
默认情况下,参数处于关闭状态,并保存最近15次的运行结果。
查看当前版本是否支持
SHOW VARIABLES LIKE 'profiling';
开启功能
默认关闭,使用前需要开启
运行sql语句
SELECT * FROM emp GROUP BY id%10 LIMIT 150000;
SELECT * FROM emp GROUP BY id%20 ORDER BY 5;
查看结果
SHOW profiles;
诊断sql语句
# n为上一步sql的Query_ID
SHOW profile cpu,block io FOR QUERY n;
各个参数的含义为:
日常开发需要注意的结论
SELECT * FROM emp GROUP BY id%20 LIMIT 120000;
SELECT * FROM emp GROUP BY id%20 ORDER BY 5;
尽量不要在生产环境开启该功能。
在mysql的my.cnf中,设置如下:
# 开启
general_log=1
# 记录日志文件的路径
general_log_file=/path/logfile
# 输出格式
log_output=FILE
# 开启
set global general_log=1;
# 全局日志可以存放到日志文件中,也可以存放到Mysql系统表中
# 存放到日志中性能更好一些
# 存储到表中:
set global log_output='TABLE';
# 之后,编写的sql语句将会记录到mysql库里的general_log表,可以用下面的命令查看
select * from mysql.general_log;