1. 程式人生 > >MySQL利用自定義函式和儲存過程建立海量表,並使用索引優化

MySQL利用自定義函式和儲存過程建立海量表,並使用索引優化

昨天學習韓順平老師的視訊時明白了上一章explain的意義,為了自己的聯絡,我學著建立了一個海量表,供自己練習使用。

程式碼如下:

#建立表DEPT  
  
  
  
CREATE TABLE dept( /*部門表*/  
deptno MEDIUMINT   UNSIGNED  NOT NULL  DEFAULT 0,  
dname VARCHAR(20)  NOT NULL  DEFAULT "",  
loc VARCHAR(13) NOT NULL DEFAULT ""  
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;  
  
  
  
#建立表EMP僱員  
CREATE TABLE emp  
(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=MyISAM DEFAULT CHARSET=utf8 ;  
  
#工資級別表  
CREATE TABLE salgrade  
(  
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,  
losal DECIMAL(17,2)  NOT NULL,  
hisal DECIMAL(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  function rand_string $$  
  
#這裡我建立了一個函式.  
  
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 ;  
select rand_string(6);  
  
# 隨機產生部門編號  
delimiter $$  
drop  function rand_num $$  
  
#這裡我們又自定了一個函式  
create function rand_num( )  
returns int(5)  
begin  
 declare i int default 0;  
 set i = floor(10+rand()*500);  
return i;  
  end $$  
  
  
delimiter ;  
select rand_num();  
  
#******************************************  
#向emp表中插入記錄(海量的資料)  
  
  
delimiter $$  
drop procedure insert_emp $$  
  
  
  
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 values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());  
  until i = max_num  
 end repeat;  
   commit;  
 end $$  
  
  
delimiter ;  
#呼叫剛剛寫好的函式, 1800000條記錄,從100001號開始  
call insert_emp(100001,1800000);  
  
  
#**************************************************************  
#  向dept表中插入記錄  
  
delimiter $$  
drop procedure insert_dept $$  
  
  
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 values ((start+i) ,rand_string(10),rand_string(8));  
  until i = max_num  
 end repeat;  
   commit;  
 end $$  
  
  
delimiter ;  
call insert_dept(100,10);  
  
  
  
  
  
#------------------------------------------------  
#向salgrade 表插入資料  
delimiter $$  
drop procedure insert_salgrade $$  
create procedure insert_salgrade(in start int(10),in max_num int(10))  
begin  
declare i int default 0;  
 set autocommit = 0;  
 ALTER TABLE emp DISABLE KEYS;    
 repeat  
 set i = i + 1;  
 insert into salgrade values ((start+i) ,(start+i),(start+i));  
  until i = max_num  
 end repeat;  
   commit;  
 end $$  
delimiter ;  
#測試不需要了  
#call insert_salgrade(10000,1000000);  
  
  
  
  
  
#----------------------------------------------  

首先建立了一個180W條資料的資料表


覺得太少,機器速度略快 不利於聯絡,又建立了9820W的資料

(臥槽 圖掛了)

貌似有點玩拖了……建立的過程中出現了很多有意思的資料

(臥槽 圖掛了)

就是一大堆臨時檔案……

20分鐘之後 變成這樣了 這個MYD檔案一直在增長 

(臥槽 圖掛了)

插了兩千萬條資料 感覺差不多了。

(臥槽 圖掛了)

弄個整數比較好操作,刪刪改改最後有1400W條

(臥槽 圖掛了)


啟動慢查詢


然後測試一個sql語句 發現很慢 4秒多,然後建立索引


索引檔案大約佔1/4-1/3


速度比較


確實牛逼的多!至於explain 需要一個專門的學習筆記來記錄。

突然知道了怎麼複製powershell的程式碼,方便多了!

mysql> show variables like 'slow%';
+---------------------+-------------------------------------------------------------+
| Variable_name       | Value                                                       |
+---------------------+-------------------------------------------------------------+
| slow_launch_time    | 2                                                           |
| slow_query_log      | OFF                                                         |
| slow_query_log_file | e:\wamp\bin\mysql\mysql5.6.17\data\2013-20140912XV-slow.log |
+---------------------+-------------------------------------------------------------+
3 rows in set (0.00 sec)

mysql> set slow_query_log="on";
ERROR 1229 (HY000): Variable 'slow_query_log' is a GLOBAL variable and should be set with SET GLOBAL
mysql> exit
Bye
PS E:\wamp\bin\mysql\mysql5.6.17\bin> cd E:\wamp\bin\mysql\mysql5.6.17\bin
PS E:\wamp\bin\mysql\mysql5.6.17\bin> mysqld -slow-query-log;
PS E:\wamp\bin\mysql\mysql5.6.17\bin> mysql -u root -p
Enter password: *****
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 44
Server version: 5.6.17 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from emp where empno=2345678;
ERROR 1046 (3D000): No database selected
mysql> select * fromlustudy.emp where empno=2345678;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
 for the right syntax to use near 'fromlustudy.emp where empno=2345678' at line 1
mysql> select * from lustudy.emp where empno=2345678;
+---------+--------+----------+-----+------------+---------+--------+--------+
| empno   | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+---------+--------+----------+-----+------------+---------+--------+--------+
| 2345678 | zfflMc | SALESMAN |   1 | 2017-10-13 | 2000.00 | 400.00 |     37 |
+---------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (3.97 sec)

mysql> show variables like 'long%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

mysql> set long_query_time=2;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'long%';
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 2.000000 |
+-----------------+----------+
1 row in set (0.00 sec)

mysql> select * from lustudy.emp where empno=2345678;
+---------+--------+----------+-----+------------+---------+--------+--------+
| empno   | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+---------+--------+----------+-----+------------+---------+--------+--------+
| 2345678 | zfflMc | SALESMAN |   1 | 2017-10-13 | 2000.00 | 400.00 |     37 |
+---------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (3.97 sec)

mysql> show variables like 'slow%';
+---------------------+-------------------------------------------------------------+
| Variable_name       | Value                                                       |
+---------------------+-------------------------------------------------------------+
| slow_launch_time    | 2                                                           |
| slow_query_log      | OFF                                                         |
| slow_query_log_file | e:\wamp\bin\mysql\mysql5.6.17\data\2013-20140912XV-slow.log |
+---------------------+-------------------------------------------------------------+
3 rows in set (0.00 sec)

mysql> set slow_query_log="On";
ERROR 1229 (HY000): Variable 'slow_query_log' is a GLOBAL variable and should be set with SET GLOBAL
mysql> set globa slow_query_log ="On";
ERROR 1193 (HY000): Unknown system variable 'globa'
mysql> set global slow_query_log ="On";
Query OK, 0 rows affected (0.09 sec)

mysql> select * from lustudy.emp where empno=2345678;
+---------+--------+----------+-----+------------+---------+--------+--------+
| empno   | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+---------+--------+----------+-----+------------+---------+--------+--------+
| 2345678 | zfflMc | SALESMAN |   1 | 2017-10-13 | 2000.00 | 400.00 |     37 |
+---------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (3.98 sec)

mysql> select * from lustudy.emp where empno=2345679;
+---------+--------+----------+-----+------------+---------+--------+--------+
| empno   | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+---------+--------+----------+-----+------------+---------+--------+--------+
| 2345679 | gvKorO | SALESMAN |   1 | 2017-10-13 | 2000.00 | 400.00 |    463 |
+---------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (4.07 sec)

mysql> explain select * from 6666666;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
 for the right syntax to use near '6666666' at line 1
mysql> explain select * from emp where empno=6666666;
ERROR 1046 (3D000): No database selected
mysql> use lustudy;
Database changed
mysql> explain select * from emp where empno=6666666;
+----+-------------+-------+------+---------------+------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows     | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL | 14000000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+----------+-------------+
1 row in set (0.00 sec)

mysql>  select * from emp where empno=6666666;
+---------+--------+----------+-----+------------+---------+--------+--------+
| empno   | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+---------+--------+----------+-----+------------+---------+--------+--------+
| 6666666 | MdiDsf | SALESMAN |   1 | 2017-10-13 | 2000.00 | 400.00 |    219 |
+---------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (4.12 sec)

mysql> alter table emp add index(empno);
Query OK, 14000000 rows affected (24.93 sec)
Records: 14000000  Duplicates: 0  Warnings: 0

mysql> select * from emp where emp =6666666;
ERROR 1054 (42S22): Unknown column 'emp' in 'where clause'
mysql> select * from emp where empno =6666666;
+---------+--------+----------+-----+------------+---------+--------+--------+
| empno   | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+---------+--------+----------+-----+------------+---------+--------+--------+
| 6666666 | MdiDsf | SALESMAN |   1 | 2017-10-13 | 2000.00 | 400.00 |    219 |
+---------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (0.03 sec)

mysql>