MySQL利用存储过程批量插入数据

时间问题,sql代码是自己写的,文本描述是复制的,内容有差异的请自己辨别

首先我是简单的写了一个mysql的循环插入数据的SP,具体如下:

DROP PROCEDURE IF EXISTS prod_dt;
CREATE PROCEDURE prod_dt()
BEGIN
DECLARE i int;
set i = 0;
WHILE i<1000000 DO
	INSERT INTO `topic`( `name`, `image`, `anwer_a`, `anwer_a_image`, `anwer_b`, `anwer_b_image`, `answer_c`, `answer_c_image`, `anwer_d`, `answer_d_image`, `true_answer`, `author_id`, `difficulty`, `topic_type`, `tag_ids`, `show_id`, `show_detail_id`, `status`, `topic_introduce`, `use_status`) VALUES ( '题目名称', '题目图片', '答案a', '答案a图片', '答案b', '答案b图片', '答案c', '答案c图片', '答案d', '答案d图片', NULL, 1, 1, 1, '3', 3, 1, 2, '题目释义', 1);
SET i = i+1;
END WHILE;
END;

call prod_dt();

这是插入100W数据的过程和结果,可以看到是换了55min +20S约3320秒(约300rows/s),看到之后我是只崩溃,就在网上查了些提速的方法:

最快的当然是直接 copy 数据库表的数据文件(版本和平台最好要相同或相似);1. 设置 innodb_flush_log_at_trx_commit = 0 ,相对于 innodb_flush_log_at_trx_commit = 1 可以十分明显的提升导入速度;2. 使用 load data local infile 提速明显;3. 修改参数 bulk_insert_buffer_size, 调大批量插入的缓存;4. 合并多条 insert 为一条: insert into t values(a,b,c), (d,e,f) ,5. 手动使用事物

在这里插入图片描述
而我创建的是Innodb类型的表,分了128个分区。而我依照以上的方法,设置如下:

DROP PROCEDURE IF EXISTS prod_dt;
CREATE PROCEDURE prod_dt()
BEGIN
DECLARE i int;
set i = 0;
WHILE i<100000 DO
	INSERT INTO `zjc_topic`( `name`, `image`, `anwer_a`, `anwer_a_image`, `anwer_b`, `anwer_b_image`, `answer_c`, `answer_c_image`, `anwer_d`, `answer_d_image`, `true_answer`, `author_id`, `difficulty`, `topic_type`, `tag_ids`, `show_id`, `show_detail_id`, `status`, `topic_introduce`, `use_status`) VALUES ( '题目名称', '题目图片', '答案a', '答案a图片', '答案b', '答案b图片', '答案c', '答案c图片', '答案d', '答案d图片', NULL, 1, 1, 1, '3', 3, 1, 2, '题目释义', 1);
SET i = i+1;
END WHILE;
END;

TRUNCATE TABLE zjc_topic;

SET SESSION unique_checks=0;
SET SESSION autocommit=0;

call prod_dt();

SET SESSION unique_checks=1;
SET SESSION autocommit=1;

可以明显的看到插入百万数据是100S左右,速度提升了33倍之多。

速度是提升了不少,那就加大插入的数据量,提升10倍,即插入千万的数据量,具体的SP如下:
varchar字段

  • 字段的限制在字段定义的时候有以下规则: a) 存储限制 varchar 字段是将实际内容单独存储在聚簇索引之外,内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过65535。 b) 编码长度限制 字符类型若为gbk,每个字符最多占2个字节,最大长度不能超过32766;   字符类型若为utf8,每个字符最多占3个字节,最大长度不能超过21845。   对于英文比较多的论坛 ,使用GBK则每个字符占用2个字节,而使用UTF-8英文却只占一个字节。   若定义的时候超过上述限制,则varchar字段会被强行转为text类型,并产生warning。 c) 行长度限制   导致实际应用中varchar长度限制的是一个行定义的长度。 MySQL要求一个行的定义长度不能超过65535。若定义的表长度超过这个值,则提示   ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to    change some columns to TEXT or BLOBs。

在这里插入图片描述
再次升级插入的数据量,提升10倍,看插入的时间及占用的内存,字段的字节同样为1000,具体的SP和结果如下:

从上图可以清楚的看到,插入1亿条数据的时间为5hours +20 min+ 56s=19256s,平均插入的条数为(5193 rows/s)。根上次插入1千万条的时间差不多,再看所耗磁盘空间,用了98G的空间,跟上次插入千万条数据时的(26G-17G=9G)也是成线性关系的。按照本机500G的磁盘空间,存储1行1K字节大小的数据,本机可以存储理想极限情况下为5亿条数据,保守为4~4.5亿左右合适,以防其他的应用或者数据库的UNDO,索引空间占用。

最后再看一次查询的时间,上次插入百万数,查询数据量的时间
在这里插入图片描述
因为创建了索引,在查百万级的数据量时,时间是1秒左右,在数据量上升到千万时,查询1亿5百万时,时间为3Min 30S,再插入1亿数据,查询数据量,时间达到27min 43s,可见,不是线性关系,是几何级增加的。

现在描述集群环境的测试

集群:32G内存 ,500G硬盘,3台虚拟机也就是3个节点:188.188.2.181(主节点,数据节点和SQL节点)、188.188.2.182(数据节点和SQL节点)和188.188.2.183(数据节点和SQL节点)。/root目录分区磁盘空间200G(原先默认的是50G)、插入的数据量为8000KW,所占磁盘空间为下图
在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章