利用存储过程和函数进行批量数据的添加
今天利用闲暇时间想学习一些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进行优化,所以分析执行计划很重要
索引优化
上面讲到子查询的优化,以及如何建立索引,而且在多个字段索引时,分别对字段建立了单个索引
后面发现其实建立联合索引效率会更高,尤其是在数据量较大,单个列区分度不高的情况下。
单列索引
多列索引
本文重点还是存储过程和 函数 实现批量添加!