测试学习(1) - 批量生成数据

项目中遇到一个问题,就是需要模拟用户创造上万数据,来进行一定数据压力下的测试,这时候我们就需要思考,到底使用哪种方式来进行数据的创建。
数据的创建有很多种,如直接sql写入,或者软件接口写入。个人建议,如果是前后逻辑关联性不大的表,可以使用数据写入的方式,因为这种方式写入速度极快与接口写入速度相比,是更快的。但如果是前后关联性比较大的表格,最好还是使用接口模拟的方式,因为这种方式通常更能贴切用户的实际使用情况,并且能够保证数据质量。

接下来,我们可以看这样一个问题:
如果造10w条测试数据,如何在数据库插入10w条数据,并且数据不重复

  • 插入数据

首先我要插入的 SQL 语句,需每条 id 不重复 ,下面是执行单个插入语句

 INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) 
 VALUES ('1', '', 'test123', '2019-12-17');

10w 太多执行时间长,用 python 先生成 1w条测下执行时间。

首先要生成多个insert 语句,这里我用 python 语言写段生成sql的脚本。

用 %s 替换需要变的字段值,如果有多个值都需要变,可以用多个%s替换对应值,我这里设计的表,只要id不一样就可以插入成功。
用for 循环,每次循环 id 加1,这样 id 就可以保证不会重复,否则插入数据库时有重复的无法写入成功。
a 是追加写入
每条sql后面分号隔开
每次写入数据,最后面加\n 换行

for i in range(10000):
    a = "INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) VALUES ('%s', '', 'test123', '2019-12-17');"%str(i+1)
    with open("a.txt", "a") as fp:
        fp.write(a+"\n")

执行python代码,在本地生成一个 a.text 文件,打开生成的数据,部分如下

INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) VALUES ('1', '', 'test123', '2019-12-17');
INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) VALUES ('2', '', 'test123', '2019-12-17');
INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) VALUES ('3', '', 'test123', '2019-12-17'); 
INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) VALUES ('4', '', 'test123', '2019-12-17'); 
...... 
INSERT INTO `apps`.`apiapp_card` (`id`, `card_id`, `card_user`, `add_time`) VALUES ('10000', '', 'test123', '2019-12-17');

执行完成花了5分钟左右,也就是说10w条得50分钟,这太慢了,要是数据更多,会等太久,不是我们想要的效果!

  • 批量执行

由于单个执行,花费时间太长,现在需要优化下改成一个 inert 语句,改成批量插入数据,只写一个 insert into 这样一次性批量写到数据库,会快很多。

可以将SQL语句进行拼接,使用 insert into table () values (),(),(),()然后再一次性插入。

批量执行要么全部成功,要么一个都不会写入成功,当写的 SQL 语法有问题时就不会写入成功了。

需注意: 拼接 sql ,多个values 值中间用英文逗号隔开 value 值要与数据表的字段一一对应,一定要注意最后一条数据后面不是逗号,改成分号

insert_sql = "INSERT INTO `apps`.`apiapp_card`  VALUES "
with open("b.txt", "a") as fp:
        fp.write(insert_sql+"\n")
for i in range(10000):
    a = "('%s', '', 'test123', '2019-12-17'),"%str(i+10001)
    with open("b.txt", "a") as fp:
        fp.write(a+"\n")

执行完成后,复制 b.text 文件的内容,需注意的是这里一定要改成 ;结尾,否则语法报错

部分数据内容展示如下

INSERT INTO `apps`.`apiapp_card` VALUES 
('10001', '', 'test123', '2019-12-17'),
('10002', '', 'test123', '2019-12-17'),
......
('20000', '', 'test123', '2019-12-17');

复制生成的 INSERT INTO 到 navicat 客户端执行

执行完成,最后看的测试结果,1w条数据只用了0.217秒,速度明显提高不少。

10w数据插入

接着测下,当生成10 w条数据的时候,会花多少时间?

直接插入mysql 这时候会有报错:Err 1153 - Got a packet bigger than ‘max_allowed_packet’ bytes
报错原因:由于数据量较大,mysql 会对单表数据量较大的 SQL 做限制,10w条数据的字符串超出了max_allowed_packet*的允许范围。
解决办法:需修改mysql 数据库的max_allowed_packet的值,改大一点

  • max_allowed_packet

先在 navicat 输入命令查看 max_allowed_packet 最大允许包

SHOW GLOBAL VARIABLES LIKE "max_allowed_packet";

查看到 value 值是 4194304, 最大限制是 40 M,我们只需的sql字符串太大了,超出了这个范围。

在 navicat 客户端我们无法直接修改对应 value值,需登录到mysql,用命令行修改。修改完毕后再次重新执行上面10w条数据,查看运行结果总共花11秒左右时间。

上面的方法只能临时生效,当重启mysql后,你会发现又还原回去了。
这里还有一种永久生效的方法,需修改my.cnf配置文件
在[mysqld]部分添加一句,如果有就修改对应的值:

max_allowed_packet=40M

这里的值,可以用 M单位,修改后,需要重启下mysql就可以生效了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值