后端开发技巧,快速生成一个测试数据表
编写代码前,我们应该对设计的表进行测试,或者说快速生成一些数据,以便在调试程序时使用,这是非常必要的。
无论是性能测试,还是数据分页,数据筛选,在功能开发时总需要一些可用数据(毕竟手写太慢了)。
从建表开始
首先,drop table if exists ,然后就是建表啦。(和其他教程不一样,推荐先建表,然后 update 数据,这样更方便控制些,而且说不定后面也要修改某列的值)
建表后,首先插入10条空数据,然后使用蠕虫复制,即可快速生成千万数据,例如:(当然也没有必要,除了性能测试外,一般生成几百条就够了)
<? php
//删除表
DB::sql("drop table if exists `hua_blog`")->update();
//建立表
DB::sql("CREATE TABLE `hua_blog` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
`title` varchar(1000) NOT NULL DEFAULT '自动存稿' COMMENT '文章标题',
`body` longtext NOT NULL COMMENT '文章内容',
`type` int(1) NOT NULL DEFAULT '1' COMMENT '文章类型{1.博客,2.随笔,3.学习,4.隐私}',
`date` int(10) NOT NULL COMMENT '更新时间',
`uid` bigint(20) NOT NULL DEFAULT '1' COMMENT '用户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4;")->update();
//循环插入10条数据
for ($i=0; $i<10; $i++){
DB::sql("insert into `hua_blog`(title,body,type,date,uid) values('','',0,0,0)")->update();
}
//蠕虫复制,生成 2^n 的倍数(比如 n=10 ,也就是 2^n * 10 = 10240条)
/*
* 5 == 320条
* 10 == 1万条
* 14 == 16万条
* 17 == 130万条
* 19 == 500万条
* 20 == 1000万条 (建议不超过一万条,容易超时失败)
* 21 == 2000万条
* 22 == 4000万条
* 23 == 8000万条
* 24 == 1亿6千万条
*/
for ($i=0;$i<5;$i++){
DB::sql("insert into hua_blog(title,body,type,date,uid) select title,body,type,date,uid from hua_blog")->update();
}
给每个字段赋随机值
推荐尽可能写在 sql 文件中,然后执行整个 sql 文件,这样更方便,而且易于迁移。
例如我们有以下 blog.sql
-- 设置随机 title
update hua_blog set `title`=CONCAT('标题',CHAR ((48+floor(rand()*9))));
-- 设置随机 body
drop table if EXISTS rand_insert;
CREATE TABLE `rand_insert` (
`id` int NOT NULL AUTO_INCREMENT,
`type_str` varchar(255) NOT NULL DEFAULT '' COMMENT '字符串值',
`type_int` int NOT NULL DEFAULT 0 COMMENT '整数值',
`type_float` decimal(10, 2) NOT NULL DEFAULT 0.00 COMMENT '浮点数值',
PRIMARY KEY (`id`)
);
insert into rand_insert(type_str) values('细心谨慎。勤奋好学…但是,“自我评价”里千万不要空洞的写出这些优点,最好结合自己的实际经验,重点描述'),
('细心严谨:在xx公司xx岗位实习期间,没出现数据分析错误…类似这样的自我评价。'),('事实求是是整个简历内容必须具有的品质,弄虚作假,夸大其词的简历,会让HR感到浮夸而且不着边际。'),
('事实求是是整个简历内容必须具有的品质,弄虚作假,夸大其词的简历,会让HR感到浮夸而且不着边际。'),('简历是一份正式的书面文件,是向面试官推荐自己的第一手资料,所以,措词上我们得尽量避免口语化。'),
('“自我评价”中描述自己的闪光点等方面所使用的词语应该严谨、平实,让HR在阅读简历时可以充分感受到你对这份工作的诚恳态度。'),
('本人性格开朗,对待事情有较强的积极性和责任性,在工作上多次受到上级管理人员的认可,当然最重要的是能力。'),
('本人性格开朗,对待事情有较强的积极性和责任性,在工作上多次受到上级管理人员的认可,当然最重要的是能力。'),
('诚诚恳恳、执着的敬业精神是我最大的优点和财富,期待与您的面谈!'),
('我是个乐观积极向上的女孩,喜欢去挑战一些自己从没做过的事情,愿意与人合作,有着比较强烈的集体荣誉感。'),
('平时喜欢上网看电影,或是偶尔搜集一些有趣的趣闻,没什么特别的兴趣,喜欢参加集体活动,很喜欢排球和乒乓球,还有喜欢听音乐 跳舞。'),
('平时喜欢上网看电影,或是偶尔搜集一些有趣的趣闻,没什么特别的兴趣,喜欢参加集体活动,很喜欢排球和乒乓球,还有喜欢听音乐 跳舞。'),
('这是我从事一年酒店以来得出的结论,虽然经验还不算丰富,但是与客户的互动中学会了很多,并且希望继续从事这个行业。'),
('简历是你的敲门砖!通过简历才有机会入职!'),
('最后offer先生来放福利了,针对春招,同学们的简历修改福利来了!'),
('最后offer先生来放福利了,针对春招,同学们的简历修改福利来了!'),
('“个人优势”撰写的实操方法,还附上了面试会遇到的“特殊情况”,供大家参考,以便及时修正简历,希望你能顺利求职哦!'),
('很多小伙伴在写“个人优势”时特别容易写成流水账,主要原因就是没有写出来缘由,因果关系不协调。');
update hua_blog set body =(select type_str from rand_insert order by rand() limit 1);
-- 设置随机 type
update hua_blog set `type` = ceil(rand()*4);
-- 设置随机 date (一年前,到一个月前之间)
update hua_blog set `date` = unix_timestamp(current_timestamp)-floor(30+rand()*335)*86400;
-- 设置随机 uid (从 user 表中随机取用户id)
update hua_blog set `uid` = (select `id` from `hua_user` where `type`=2 order by rand() limit 1);
接下来,我们在程序中,调用方法,一次性执行该sql
//执行一个sql文件,以便快速赋值(而且sql更易于移植)
$res = DB::exeSqlFile(__DIR__."/blog.sql");
执行的原理:(实际上非常简单,只需要一次性读取 sql 文件中的内容,然后 ; 分割一下,循环执行即可)
/**
* 执行 sql 文件(注意不能执行超大 sql)
* @param $file
* @return bool
*/
public static function exeSqlFile($file){
//检测文件是否存在
if(!file_exists($file)){
return error_msg("文件不存在");
}
//判断文件大小(不得大于50mb)
$size = filesize($file);
if($size>1024*1024*50){
return error_msg("文件不得大于50mb");
}
//取得文件内容
$file = file_get_contents($file);
$sqlArr = explode(";",$file);
foreach ($sqlArr as $sql){
self::sql($sql)->update();
}
}
按理来说,对一些简单的数据已经能快速赋随机值了,但是对于一些复杂的数据,需要在程序中处理,例如:
//对于一些难以随机赋值的,或要求高的,编程实现随机赋值(这里仅测试 id<50,再次随机赋值body)
$bodyText = array('标签1','标签2','标签3','标签4','标签5');
for ($i=0; $i<50; $i++){
$rand = random_int(1,3); // 随机取 1 个值,或 2 个值,或 3个值
$key = array_rand($bodyText,$rand);
if(is_int($key)) {
$key = array($key);
}
$val = array();
foreach ($key as $item){
$val[] = $bodyText[$item];
}
$insert_str = join("||",$val); // 值1 或者 值1||值2 或者 值1||值2||值3
$res = DB::sql("update `hua_blog` set `body`='".$insert_str."' where id=".$i)->update();
$a = 1;
}
总结一下
按照以上步骤,通常你只需要一个 sql 文件,以及一个 php 文件足够。
每次生成数据,访问一下 php 页面,即可从删表,建表、插入海量数据,以及给每个字段设置随机值等,一次执行完毕,非常方便。
对于数据量超大,比 1 千万还要大得多,比如 10 亿什么的,最好不要一次性生成,先生成一千万,然后在数据库工具里执行蠕虫复制的sql,多来两下。因为 php 页面容易超时,即使设置长一些时间,也不好,不如专业数据库管理工具来得实在,起码有个计时功能,看它执行了多少秒。
测试蠕虫复制生成1000万数据,大概70秒左右,并不是很慢可以接收,而且一般不会需要这么大的数据。
除了以上程序+sql的方式,纯sql可以考虑存储过程,但是一般情况下用程序和sql脚本配合更简单些,毕竟会写存储过程的人较少。
文章作者: 朱丰华
文章链接: https://smart.52dixiaowo.com/blog/post-59.html
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。