1. 程式人生 > >MYSQL的查詢優化(學習優化sql的步驟)

MYSQL的查詢優化(學習優化sql的步驟)

1.慢查詢

mysql自身是有一個慢查詢時間和慢查詢記錄的,但是在預設情況下,我們的mysql不會記錄慢查詢,需要在啟動mysql時候,指定記錄慢查詢才可以

(1)使用show variables like 'long_query_time'命令,檢視慢查詢時間

現在慢查詢時間是10s,但是我們可以通過set long_query_time對其進行臨時修改(關閉掉這次會話之後慢查詢時間會被重置回10)

另外,我們也可以通過show variables like '%slow%'這個命令來檢視慢查詢的配置

慢查詢日誌預設是不啟用的,所以我們要開啟它,有兩種方法,一種是用set重新設定變數,另一種就是直接修改配置檔案,這裡建議用修改變數的方法(因為是臨時的)

想要測試是否開啟慢查詢,可以使用select sleep(3),執行之後去對應的目錄找到慢查詢日誌是否有記錄就可以了,這裡就不再多說了。

 

2.構建大資料量進行測試

因為之前優化的查詢裡面儲存著客戶的資料,這裡不方便用於展示,所以我們可以自己來構建一個大資料的表,這裡就用到了mysql的儲存過程(使用儲存過程無非就是想要插入資料執行的時間減少而已,其實我們可以通過php寫程式碼批量插入)

儲存過程怎樣寫我就不多說了,而且網上也能找到大量的測試資料程式碼,所以這裡我就直接上程式碼了

(1)建立表

CREATE TABLE dept(

deptno MEDIUMINT   UNSIGNED  NOT NULL  DEFAULT 0 COMMENT '編號', 

dname VARCHAR(20)  NOT NULL  DEFAULT "" COMMENT '名稱',

loc VARCHAR(13) NOT NULL DEFAULT "" COMMENT '地點'

) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

 

CREATE TABLE emp (

empno  MEDIUMINT UNSIGNED  NOT NULL  DEFAULT 0 COMMENT '編號',

ename VARCHAR(20) NOT NULL DEFAULT "" COMMENT '名字',

job VARCHAR(9) NOT NULL DEFAULT "" COMMENT '工作',

mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '上級編號',

hiredate DATE NOT NULL COMMENT '入職時間',

sal DECIMAL(7,2)  NOT NULL COMMENT '薪水',

comm DECIMAL(7,2) NOT NULL COMMENT '紅利',

deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '部門編號'

)ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

 

分別是部門表(dept)和員工表(emp),這裡我是故意沒有建立主鍵,等下留作演示用

 

(2)建立自定義函式

delimiter $$

 

建立一個自定義函式,目的是返回1-10的隨機數

create function rand_num() 
returns int
begin 
  return floor(1+rand()*10);
end$$

 

建立一個自定義函式,目的是返回隨機字串

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$$

為了能使儲存過程正常執行,要先把mysql的語句結束符號修改成$$,建立完後用delimiter命令改回;就可以了

 

(3)建立插入資料的儲存過程

create procedure insert_emp(in start int(10),in max_num int(10))
begin
declare i int default 0; 
#set autocommit =0 把autocommit設定成0
 set autocommit = 0;  
 repeat
 set i = i + 1;
 insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
  until i = max_num
 end repeat;
   commit;
 end $$

 

(4)呼叫call insert_emp(100001,4000000)建立400w條資料

插入400w條資料用了8分半鐘,這時我們可以去看下慢查詢日誌是否記錄了

 

 

3.查詢優化

首先,我們在沒有索引的情況下,對員工表進行查詢

查詢員工號為300w的資料,用時32.11s,這估計是誰都不能忍的事,要是被老闆發現了,估計就要直接掀桌了,所以我們就用explain工具來分析一下這條查詢

 

那麼,現在我們為員工編號加上主鍵索引,結果又會如何呢

只用了0.03秒,查詢效率提高了1000倍以上!

現在我們來分析一下這個查詢語句吧

 

那麼,現在我們來試試多表查詢的情況,先向部門表插入幾條資料,這裡就不再多說了

可以發現,用了51s才查詢完畢(因為資料過多,所以用ctrl+c中斷輸出,這裡補充上查詢語句select * from dept left join emp on dept.deptno=emp.deptno where dept.deptno=1;)

 

用explain分析可以看出兩個表都是全表掃描

為emp表加上deptno的索引後,查詢結果和分析結果如下

只用了7.34s,而且查詢數量明顯相比第一次只查詢了不到40w條,查詢效率提高了7倍以上

然而我們也發現了,dept表仍然沒有用到索引,所以我們試試看為dept表加上主鍵索引

雖然有所優化,但是並不明顯,其實上述實驗結果也可以看出,總查詢條數(rows)/總資料量的比值越小,索引優化查詢的效果越明顯

 

mysql的查詢優化就暫時先介紹到這裡了,想要具體的對mysql進行優化,其實還需要explain各引數的詳解和使用索引的注意事項等