1. 程式人生 > >MySQL模擬插入百萬級資料和SQL分析

MySQL模擬插入百萬級資料和SQL分析

一、引言

測試環境中的資料,有時候需要我們自己來構造,為了模擬大資料量,我們總不能一條一條SQL的往資料庫中插入,我們可以使用函式和儲存過程來實現,這就需要對MySQL的函式和儲存過程所有掌握,下面就來介紹一下如何模擬百萬資料或者千萬資料的插入。(資料模擬完成後,還可以用這些資料來測試MySQL的訪問效能哦)

二、MySQL模擬插入百萬級資料:

1、建表部門表和員工表
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 "" );
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, comn decimal(7,2) not null, deptno mediumint unsigned not null default 0 );
2、設定引數 log_bin_trust_function_creators;

前提說明:如果我們在建立函式時,報錯:this function has none of deterministic…,這是由於開啟過慢查詢日誌,因為開啟了bin-log(二進位制日誌),我們就必須為我們的function指定一個引數。

簡單介紹一下,當二進位制日誌啟用後,這個變數就會啟用。它控制是否可以信任儲存函式建立者,不會建立寫入二進位制日誌引起不安全事件的儲存函式。如果設定為0(預設值),使用者不得建立或修改儲存函式,除非它們具有除CREATE ROUTINE或ALTER ROUTINE特權之外的SUPER許可權,如果變數設定為1,MySQL不會對建立儲存函式實施這些限制。

那麼為什麼MySQL有這樣的限制呢? 因為二進位制日誌的一個重要功能是用於主從複製,而儲存函式有可能導致主從的資料不一致。所以當開啟二進位制日誌後,引數log_bin_trust_function_creators就會生效,限制儲存函式的建立、修改、呼叫。

(1)、檢視該引數:

show varibales like ‘log_bin_trust_function_creators’;

(2)、設定該引數:

set global log_bin_trust_function_creators = 1;

(3)、這樣添加了引數後,如果mysqld重啟,上述引數又會消失,永久的辦法是:

a.	在Windows系統下的配置檔案中 my.ini[mysqld] 加上 log_bin_trust_function_creators = 1;
b.	在Linux下 /etc/my.cnf下my.cnf[mysqld] 加上 log_bin_trust_function_creators = 1;
3、建立函式,保證每條資料都不同
(1)、隨機產生字串
DELIMITER $$ 
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN
	DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmlopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	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 $$
(2)、隨機產生部門編號
DELIMITER $$ 
CREATE FUNCTION rand_num() RETURNS INT(5)
BEGIN
	DECLARE i INT DEFAULT 0;
	SET i = FLOOR(100+RAND()*10);
	RETURN i;
END $$
4、建立儲存過程
(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 把autocommit設定成0,把預設提交關閉
	SET autocommit = 0;
	REPEAT
	SET i = i + 1;
	INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comn,deptno) VALUES ((START+I),rand_string(6),'SALEMAN',0001,now(),2000,400,rand_num());
	UNTIL i = max_num
	END REPEAT;
	COMMIT;
END $$
(2)、建立往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 $$
5、呼叫方法儲存過程

呼叫方法和儲存過程:

delimiter ;				//結束$$的定義,變為";"
call insert_dept(10000,100000);

三、show profile

show profile 是MySQL提供用來分析當前會話中語句執行的資源消耗情況,可以用於SQL的調優的測量。預設情況下,該引數處於關閉狀態,並保持最近15次的執行結果。

1、show profile分析步驟:

(1)、看看當前的mysql版本是否支援(mysql5.5之後)

show varibles like ‘profiling’;

(2)、開啟功能,預設是關閉,使用前需要開啟。或者在配置檔案中設定該值

set profiling = on; //開啟

在這裡插入圖片描述
(3)、執行SQL;
(4)、使用該命令可以檢視第三步執行的所有SQL結果:

	show profiles;

在這裡插入圖片描述
(5)、從上圖中,可以看出14號SQL執行時間用了37.58秒,這屬於嚴重的SQL問題,想想併發情況下,這一條SQL所要話費的時間就是37秒,使用者該怎麼辦(這裡只是模仿SQL的慢查詢)。這就需要對該SQL進行診斷,我們使用如下命令:

show profile cpu,block io for query 問題SQL數字號碼;

在這裡插入圖片描述

這樣我們就可以知道該條SQL執行的每一個細節,就可以對SQL進行優化了。

2、show profile的type引數介紹:

show profile的type引數

引數 意義
all 顯示所有的開銷資訊
cpu 顯示CPU相關開銷資訊
Block io 顯示塊IO相關開銷
ipc 顯示傳送和接收相關開銷資訊
memory 顯示記憶體相關開銷資訊
Page faults 顯示頁面錯誤相關開銷資訊
swaps 顯示交換次數相關開銷的資訊
source 顯示和source_funciton、source_file、source_line相關的開銷資訊
Context switches 上下文切換相關開銷

如果在 Status 欄位中出現以下描述,則需要注意:

(1)converting HEAP to MYISAM:查詢結果太大,記憶體都不夠用了,往磁碟上搬了;

(2)Creating tmp table :建立臨時表(拷貝資料到臨時表,用完再刪除);

(3)Copying to tmp table on disk:把記憶體中臨時表複製到磁碟(很危險!!!)

(4)Locked

在這裡插入圖片描述

四、全域性查詢日誌

1、注意作用:

全域性查詢日誌用於儲存所有的SQL執行記錄,該功能主要用於測試環境,在生產環境中永遠不要開啟該功能。

(1)、在配置檔案中啟用,在mysql的my.cnf中,設定如下:

general_log = 1
general_log_file=/path/logfile			//路徑
log_output=FILE							//以檔案方式	

(2)、使用編碼啟用:

set global general_log = 1;
set global log_output = ‘table’;			//儲存到表中

此後,所編寫的sql語句,將會記錄到:mysql庫裡的general_log表,可以用下面命令檢視:select * from mysql.general_log

在這裡插入圖片描述

在這裡插入圖片描述
注意:永遠不要再生產環境開啟這個功能

五、總結:

1、通過命令方式開啟的功能,重啟mysql後都會失效;

2、全域性查詢日誌只用在測試環境,切記生產環境中永遠不要開啟該功能;

3、show profile能更細粒度的分析SQL的執行過程,要區別於explain的使用。