利用存储过程和函数进行批量数据的添加

今天利用闲暇时间想学习一些sql 的优化方法,我老早就讲 表都建好了,但是数据是一个问题呀。我需要大量的数据,我想到了可以通过硬编码的格式进行插入,但是我又不想写代码。我就想到另一个方案:存储过程和函数

由于以前我也很少写这些东西,今天我就认证的研究一下存储过程和函数的神奇地方。 吐槽完了!我们开始上枪开干....

【备注:首先检查下我们的数据库是否支持函数】

利用存储过程和函数进行批量数据的添加

若是你的不支持可以执行

set global log_bin_trust_function_creators=1;

一。首先创建三张表 

学生表 student

科目表  course

学生成绩表 sc

这里我就不展示了

二。编写函数

(1).编写一个随机生成字符串的函数:

delimiter $$
 create function rand_string(n int) returns varchar(255)
 begin
   declare chars_str varchar(100) default 'qwertyuiopasdfghjklzxcvbnm';
   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(rand()*10);
 return i;
 end $$

 创建完后我们可以查看创建的函数:

   SHOW FUNCTION STATUS

利用存储过程和函数进行批量数据的添加

可以看到我们创建的两个函数

三。编写存储过程

(1)学生表

delimiter $$
CREATE PROCEDURE INSERT_student(in START INT(10) ,in max_num INT(10) )
BEGIN
    DECLARE i int DEFAULT 1;
    SET autocommit = 0;  /*把autocommit设置成0*/
    REPEAT
    SET i=i+1;
    INSERT INTO student(id,NAME) VALUES( (START+i), rand_string(6) );
    UNTIL i=max_num 
    END REPEAT;
    COMMIT;
END $$

利用存储过程和函数进行批量数据的添加

(2)科目表

delimiter $$
CREATE PROCEDURE INSERT_course(in START INT(10) ,in max_num INT(10) )
BEGIN
    DECLARE i int DEFAULT 1;
    SET autocommit = 0;  /*把autocommit设置成0*/
    REPEAT
    SET i=i+1;
    INSERT INTO course(c_id,NAME) VALUES( (START+i), '语文' );
    UNTIL i=max_num 
    END REPEAT;
    COMMIT;
END $$

利用存储过程和函数进行批量数据的添加

(3).成绩表

delimiter $$
CREATE PROCEDURE INSERT_sc(in START INT(10) ,in max_num INT(10) )
BEGIN
    DECLARE i int DEFAULT 1;
    SET autocommit = 0;  /*把autocommit设置成0*/
    REPEAT
    SET i=i+1;
    INSERT INTO sc(sc_id,s_id,c_id,score) VALUES( (START+i), rand_num(),rand_num(),rand_num()  );
    UNTIL i=max_num 
    END REPEAT;
    COMMIT;
END $$

利用存储过程和函数进行批量数据的添加

查看存储过程

SHOW CREATE PROCEDURE INSERT_student;
SHOW CREATE PROCEDURE INSERT_course
SHOW CREATE PROCEDURE INSERT_sc;

利用存储过程和函数进行批量数据的添加

四。调用存储过程

CALL INSERT_student(1,100) 

CALL INSERT_sc(1,1000)

call INSERT_course(1,1000)

添加相应的数据

删除存储过程

drop    PROCEDURE  存储过程名称

五。数据查询优化

查询科目为语文的并且成绩是107 的数据

SELECT * FROM student s WHERE s.id in(

SELECT sc.s_id from sc sc WHERE sc.c_id =0 AND sc.score =107 )

没建立索引之前需要 0.9多分钟

发现没有用到索引,type全是ALL,那么首先想到的就是建立一个索引,建立索引的字段当然是在where条件的字段了。

先给sc表的c_id和score建个索引

CREATE index sc_c_id_index on SC(c_id);

CREATE index sc_score_index on SC(score);

然后我就建立索引了

利用存储过程和函数进行批量数据的添加

建立索引后可以看到 type 不是 All

查询的速度是 0.0004秒

利用存储过程和函数进行批量数据的添加

我觉得还不够快,又改

SELECT * FROM student s INNER JOIN sc  sc ON s.id = sc.s_id WHERE sc.c_id =0 and sc.score=107

利用存储过程和函数进行批量数据的添加

又改成  先where 后再 join 

利用存储过程和函数进行批量数据的添加

正常情况下是先join再进行where过滤,但是我们这里的情况,如果先join,将会有70w条数据发送join,因此先执行where过滤是明智方案,现在为了排除mysql的查询优化

总结:

  • mysql嵌套子查询效率确实比较低

  • 可以将其优化成连接查询

  • 连接表时,可以先用where条件对表进行过滤,然后做表连接
    (虽然mysql会对连表语句做优化)

  • 建立合适的索引,必要时建立多列联合索引

  • 学会分析sql执行计划,mysql会对sql进行优化,所以分析执行计划很重要

索引优化

上面讲到子查询的优化,以及如何建立索引,而且在多个字段索引时,分别对字段建立了单个索引

后面发现其实建立联合索引效率会更高,尤其是在数据量较大,单个列区分度不高的情况下。

单列索引

利用存储过程和函数进行批量数据的添加

多列索引

利用存储过程和函数进行批量数据的添加

利用存储过程和函数进行批量数据的添加

 

利用存储过程和函数进行批量数据的添加

 

 

利用存储过程和函数进行批量数据的添加

 

本文重点还是存储过程和 函数 实现批量添加!