通过show status命令了解各种SQL的执行频率
MySQL客户端连接成功后,通过使用show [session|global] status 命令可以提供服务器状态信息;
其中的session来表示当前的连接的统计结果,global来表示自数据库启动至今的统计结果,默认是session级别的。
show status 常用命令:
show status like 'com_%';
其中com_xxx表示xxx语句所执行的次数;
重点注意com_select, com_insert, com_update, com_delete通过这几个参数,可以容易的了解到当前数据库应用是以插入更新为主还是以查询为主(来决定不同的存储引擎),以及各类的SQL大致执行比例是多少。
show status like 'com_insert';
show statuslike 'com_delete';
show statuslike 'com_update';
show statuslike 'com_select';
show status like 'connections'; //连接到MySQL服务器的连接数
show statuslike 'uptime'; //服务器的工作时间(单位:s)
show statuslike 'slow_queries'; //慢查询的次数(默认是慢查询时间:10S):不仅是查询,insert也包括的
如何定位慢查询(执行效率低)的SQL语句
默认情况下,MySQL认为10秒才是一个慢查询。
mysql> show variables like 'long_query_time';+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
set long_query_time=1; //修改mysql慢查询时间
mysql> set long_query_time=1;
Query OK,0 rows affected (0.00sec)
mysql> show variables like 'long_query_time';+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
注意:set只对本MySQL Client有效。当打开一个新的客户端的时候,还是默认值10秒。
也可以在my.ini中进行配置,就会全局有效:
long_query_time=1
构建一个大表(400W)用于测试mysql优化语句:
#创建表DEPTCREATE TABLE dept( /*部门表*/deptno MEDIUMINT UNSIGNEDNOT NULL DEFAULT 0,
dnameVARCHAR(20) NOT NULL DEFAULT"",
locVARCHAR(13) NOT NULL DEFAULT""
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
#创建表EMP雇员CREATE TABLEemp
(empno MEDIUMINT UNSIGNEDNOT NULL DEFAULT 0, /*编号*/enameVARCHAR(20) NOT NULL DEFAULT "", /*名字*/jobVARCHAR(9) NOT NULL DEFAULT "",/*工作*/mgr MEDIUMINT UNSIGNEDNOT NULL DEFAULT 0,/*上级编号*/hiredate DATENOT NULL,/*入职时间*/salDECIMAL(7,2) NOT NULL,/*薪水*/commDECIMAL(7,2) NOT NULL,/*红利*/deptno MEDIUMINT UNSIGNEDNOT NULL DEFAULT 0 /*部门编号*/)ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
#工资级别表CREATE TABLEsalgrade
(
grade MEDIUMINT UNSIGNEDNOT NULL DEFAULT 0,
losalDECIMAL(17,2) NOT NULL,
hisalDECIMAL(17,2) NOT NULL)ENGINE=MyISAM DEFAULT CHARSET=utf8;INSERT INTO salgrade VALUES (1,700,1200);INSERT INTO salgrade VALUES (2,1201,1400);INSERT INTO salgrade VALUES (3,1401,2000);INSERT INTO salgrade VALUES (4,2001,3000);INSERT INTO salgrade VALUES (5,3001,9999);
# 随机产生字符串
#定义一个新的命令结束符合
delimiter $$
#删除自定的函数drop functionrand_string $$
#这里创建了一个函数.
#rand_string(nINT) rand_string 是函数名 (n INT) //该函数接收一个整数create function rand_string(n INT)returns varchar(255) #该函数会返回一个字符串begin#chars_str定义一个变量 chars_str,类型是varchar(100),默认值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';declare chars_str varchar(100) default
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';declare return_str varchar(255) default '';declare i int default 0;while i
delimiter ;select rand_string(6);
# 随机产生部门编号
delimiter $$drop functionrand_num $$
#这里我们又自定了一个函数create functionrand_num( )returns int(5)begin
declare i int default 0;set i = floor(10+rand()*500);returni;end$$
delimiter ;selectrand_num();
#******************************************#向emp表中插入记录(海量的数据)
delimiter $$drop procedureinsert_emp $$
#随即添加雇员[光标]400wcreate procedure insert_emp(in start int(10),in max_num int(10))begin
declare i int default 0;
#set autocommit =0把autocommit设置成0set autocommit = 0;
repeatset i = i + 1;insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
until i=max_numendrepeat;commit;end$$
delimiter ;
#调用刚刚写好的函数, 1800000条记录,从100001号开始
call insert_emp(100001,4000000);select count(*) fromemp;#4000000#**************************************************************# 向dept表中插入记录
delimiter $$drop procedureinsert_dept $$create procedure insert_dept(in start int(10),in max_num int(10))begin
declare i int default 0;set autocommit = 0;
repeatset i = i + 1;insert into dept values ((start+i) ,rand_string(10),rand_string(8));
until i=max_numendrepeat;commit;end$$
delimiter ;
call insert_dept(100,10);
#------------------------------------------------
#向salgrade 表插入数据
delimiter $$drop procedureinsert_salgrade $$create procedure insert_salgrade(in start int(10),in max_num int(10))begin
declare i int default 0;set autocommit = 0;ALTER TABLEemp DISABLE KEYS;
repeatset i = i + 1;insert into salgrade values ((start+i) ,(start+i),(start+i));
until i=max_numendrepeat;commit;end$$
delimiter ;
#测试不需要了
#call insert_salgrade(10000,1000000);
#----------------------------------------------
事先将long_query_time设置为1
mysql> select * from emp where empno=234567;+--------+--------+----------+-----+------------+---------+--------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+--------+--------+----------+-----+------------+---------+--------+--------+
| 234567 | fgqmkp | SALESMAN | 1 | 2014-09-23 | 2000.00 | 400.00 | 444 |
+--------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (8.09 sec)
总共花费了8.09秒
mysql> show status like 'slow_queries';+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries | 2 |
+---------------+-------+
1 row in set (0.00 sec)
为什么是2???其实统计的并不只是select,前面通过存储过程插入数据也算。
将慢查询的sql记录到我们的一个日志中
在默认情况下mysql不记录慢查询日志,需要在启动的时候指定
bin\mysqld.exe --safe-mode --slow-query-log [mysql5.5 可以在my.ini指定]
bin\mysqld.exe --log-slow-queries=d:/abc.log [低版本mysql5.0可以在my.ini指定]
关闭mysql服务并启动:bin\mysqld.exe --safe-mode --slow-query-log
如果启用了慢查询日志,默认把这个文件放在my.ini 文件中记录的位置:datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
下创建了一个:hostname-slow.log的文件
由于重启了mysql服务,为了测试,则需要重新设置慢查询时间:set long_query_time=1;
mysql> select * from emp where empno=234567;+--------+--------+----------+-----+------------+---------+--------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+--------+--------+----------+-----+------------+---------+--------+--------+
| 234567 | fgqmkp | SALESMAN | 1 | 2014-09-23 | 2000.00 | 400.00 | 444 |
+--------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (8.01 sec)
那么在hostname-show.log文件中就记录下了如下慢查询信息:
# Time: 140923 22:06:13#User@Host: root[root] @ localhost [127.0.0.1]# Query_time:8.011458 Lock_time: 0.037002 Rows_sent: 1 Rows_examined: 4000000
usemysqltest;SET timestamp=1411481173;select * from emp where empno=234567;
当第二次执行相同的sql语句时,速度会快很多。