Mysql数据库优化---2.慢查询(一)

1.SQL优化的一般步骤

  •    通过show status命令了解各种SQL的执行频率。
  •    定位执行效率较低的SQL语句(重点select)
  •    通过explain分析低效率的SQL语句的执行情况
  •    确定问题并采取相应的优化措施

问题是: 如何从一个大项目中,迅速的定位执行速度慢的语句? (定位慢查询)

                 首先要找到哪些查询是慢查询

2.Show参数

2.1

  •          MySQL客户端连接成功后,通过使用show [session|global] status 命令可以提供服务器状态信息。
  1.          其中的session来表示当前的连接的统计结果,global来表示自数据库上次启动至今的统计结果。默认是session级别的。
  •         下面的例子: show status like ‘Com_%’; 其中Com_XXX表示XXX语句所执行的次数。
  •          重点注意:Com_select,Com_insert,Com_update,Com_delete通过这几个参数,可以容易地了解到当前数据库的应用是以插入更新为主还是以查询操作为主,          以及各类的SQL大致的执行比例是多少。例子
例子:
  1. show status like ‘uptime’ ; 
  2. show  stauts like ‘com_select’;
  3. show stauts like ‘com_insert’ ...类推 update  delete
  4. Mysql数据库优化---2.慢查询(一)
  5. show [session|global] status like .... 如果你不写  [session|global] 默认是session 会话,指取出当前窗口的执行,如果你想看所有(mysql 启动到现在,则应该 global)
    还有几个常用的参数便于用户了解数据库的基本情况。
  •           Connections:试图连接MySQL服务器的次数
  •          Uptime:服务器工作的时间(单位秒)
  •           Slow_queries:慢查询的次数 (默认是慢查询时间10s)
显示慢查询次数

show status like ‘slow_queries’;

Mysql数据库优化---2.慢查询(一)


2.2慢查询处理

默认情况下,mysql认为10秒才是一个慢查询.

1.修改mysql的慢查询.

   show variables like ‘long_query_time’ ; //可以显示当前慢查询时间

   set long_query_time=1 ;//可以修改慢查询时间

Mysql数据库优化---2.慢查询(一)

2.构建一个大表(400 )-> 存储过程构建
按照下面的步骤来构造一个有400万记录的表
[java] view plain copy
  1. #创建表DEPT  
  2.   
  3. CREATE TABLE dept( /*部门表*/  
  4. deptno MEDIUMINT   UNSIGNED  NOT NULL  DEFAULT 0,   
  5. dname VARCHAR(20)  NOT NULL  DEFAULT "",  
  6. loc VARCHAR(13) NOT NULL DEFAULT ""  
  7. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;  
  8.   
  9.   
  10.   
  11. #创建表EMP雇员  
  12. CREATE TABLE emp  
  13. (empno  MEDIUMINT UNSIGNED  NOT NULL  DEFAULT 0/*编号*/  
  14. ename VARCHAR(20) NOT NULL DEFAULT ""/*名字*/  
  15. job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/  
  16. mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/  
  17. hiredate DATE NOT NULL,/*入职时间*/  
  18. sal DECIMAL(7,2)  NOT NULL,/*薪水*/  
  19. comm DECIMAL(7,2) NOT NULL,/*红利*/  
  20. deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/  
  21. )ENGINE=MyISAM DEFAULT CHARSET=utf8 ;  
  22.   
  23. #工资级别表  
  24. CREATE TABLE salgrade  
  25. (  
  26. grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,  
  27. losal DECIMAL(17,2)  NOT NULL,  
  28. hisal DECIMAL(17,2)  NOT NULL  
  29. )ENGINE=MyISAM DEFAULT CHARSET=utf8;  
  30.   
  31. INSERT INTO salgrade VALUES (1,700,1200);  
  32. INSERT INTO salgrade VALUES (2,1201,1400);  
  33. INSERT INTO salgrade VALUES (3,1401,2000);  
  34. INSERT INTO salgrade VALUES (4,2001,3000);  
  35. INSERT INTO salgrade VALUES (5,3001,9999);  
  36.   
  37. # 随机产生字符串  
  38. #定义一个新的命令结束符合  
  39. delimiter $$  
  40. #删除自定的函数  
  41. drop  function rand_string $$  
  42.   
  43. #这里我创建了一个函数.   
  44.   
  45. #rand_string(n INT) rand_string 是函数名 (n INT) //该函数接收一个整数  
  46. create function rand_string(n INT) returns varchar(255) #该函数会返回一个字符串  
  47. begin   
  48. #chars_str定义一个变量 chars_str,类型是 varchar(100),默认值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';  
  49.  declare chars_str varchar(100default  
  50.    'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';  
  51.  declare return_str varchar(255default '';  
  52.  declare i int default 0;  
  53.  while i < n do   
  54.    set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));  
  55.    set i = i + 1;  
  56.    end while;  
  57.   return return_str;  
  58.   end $$  
  59.   
  60.   
  61. delimiter ;  
  62. select rand_string(6);  
  63.   
  64. # 随机产生部门编号  
  65. delimiter $$  
  66. drop  function rand_num $$  
  67.   
  68. #这里我们又自定了一个函数  
  69. create function rand_num( )  
  70. returns int(5)  
  71. begin   
  72.  declare i int default 0;  
  73.  set i = floor(10+rand()*500);  
  74. return i;  
  75.   end $$  
  76.   
  77.   
  78. delimiter ;  
  79. select rand_num();  
  80.   
  81. #******************************************  
  82. #向emp表中插入记录(海量的数据)  
  83.   
  84.   
  85. delimiter $$  
  86. drop procedure insert_emp $$  
  87.   
  88.   
  89. #随即添加雇员[光标]  400w  
  90. create procedure insert_emp(in start int(10),in max_num int(10))  
  91. begin  
  92. declare i int default 0;   
  93. #set autocommit =0 把autocommit设置成0  
  94.  set autocommit = 0;    
  95.  repeat  
  96.  set i = i + 1;  
  97.  insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());  
  98.   until i = max_num  
  99.  end repeat;  
  100.    commit;  
  101.  end $$  
  102.   
  103. delimiter ;  
  104. #调用刚刚写好的函数, 1800000条记录,从100001号开始,插入400w条记录  
  105. call insert_emp(100001,4000000);  
  106.   
  107.   
  108. #**************************************************************  
  109. #  向dept表中插入记录  
  110.   
  111. delimiter $$  
  112. drop procedure insert_dept $$  
  113.   
  114.   
  115. create procedure insert_dept(in start int(10),in max_num int(10))  
  116. begin  
  117. declare i int default 0;   
  118.  set autocommit = 0;    
  119.  repeat  
  120.  set i = i + 1;  
  121.  insert into dept values ((start+i) ,rand_string(10),rand_string(8));  
  122.   until i = max_num  
  123.  end repeat;  
  124.    commit;  
  125.  end $$  
  126.   
  127.   
  128. delimiter ;  
  129. call insert_dept(100,10);  
  130.   
  131.   
  132.   
  133.   
  134.   
  135. #------------------------------------------------  
  136. #向salgrade 表插入数据  
  137. delimiter $$  
  138. drop procedure insert_salgrade $$  
  139. create procedure insert_salgrade(in start int(10),in max_num int(10))  
  140. begin  
  141. declare i int default 0;   
  142.  set autocommit = 0;  
  143.  ALTER TABLE emp DISABLE KEYS;    
  144.  repeat  
  145.  set i = i + 1;  
  146.  insert into salgrade values ((start+i) ,(start+i),(start+i));  
  147.   until i = max_num  
  148.  end repeat;  
  149.    commit;  
  150.  end $$  
  151. delimiter ;  
  152. #测试不需要了  
  153. #call insert_salgrade(10000,1000000);  
  154.   
  155. #----------------------------------------------  

3.进行一次慢查询
要先看一下设置的慢查询的时间
Mysql数据库优化---2.慢查询(一)

Mysql数据库优化---2.慢查询(一)

4.如何把慢查询的sql记录到我们的一个日志中?

在mysql5.1中已经为我们提供了在线设置慢查询日志的方法,通过设置mysql系统变量就可以达到这个目的。这样就不用重启mysql了。

在线开启慢查询日志:
  1. mysql > set global slow_query_log=1;
  2. mysql > set global long_query_time=2;  //set long_query_time=2 才能修改成功
  3. mysql > set global slow_query_log_file='d:/mysql-slow.log';
如果不需要记录慢查询了,可以很方便的关闭:

mysql > set global slow_query_log=0;


慢查询日志中记录的一次操作:

Mysql数据库优化---2.慢查询(一)

Mysql数据库优化---2.慢查询(一)