场景:
最近正在做一个performance测试,在测试中,我必须准备大量的客户数据,以及与客户数据相关地合同数据,联系记录数据等。
客户数据为90万,合同数据达40万,联系记录数据达千万,还有一些跟踪数据达百万。
面对这样数量级的测试数据,相信大家跟我一样都会不约而同地想到使用sql语句来实现。
于是,在搞清楚数据关系之后,我开始动手写我的sql了。
为了使添加的数据更加接近真实的场景,我以客户作为起点,在添加客户后为此客户添加与之相关的合同数据,以及联系记录数据等。终于,经过连日的奋战(呵呵,可能开发人员只需要连小时地奋战),我终于把我的sql脚本写完了,并在上周五下班前kick start了脚本,大安旨意(翻译:本以为)可以在本周一看到数据生成完毕的我,却发现脚本居然还没有运行完,而且也才完成了目标的20%不到。
于是,开发人员就一同过来会诊我的脚本,发现症结如下:
1.使用太多的循环,且循环中嵌套循环;这样可以使数据关系非常清晰,但是其中使用的游标太多会严重减低数据插入的效率的。
建议,如果游标>1000的话,就不要使用循环的方式了。
2.每insert一句就commit一次,降低了运行的效率
得到了症结,当然是出解决方案啦。
1.去掉循环,使用插入数据集(dataset)的方法。
例如,有基础表TableA,其中有字段AA,AB,AC
待插入数据的表TableB,需要插入字段BA,BB,BC,且BA是可以使用表A的字段AA作为数据集的。
此时我们可以使用一下语句:
***************************
insert into TableB (BA,BB,BC)
select AA,'1','0' from TableA
***************************
如果TableA数据是,
AA,AB,AC
1,A,A
2,B,B
3,C,C
那么执行完语句后,TableB的数据是
BA,BB,CC
1,1,0
2,1,0
3,1,0
2.在使用where语句时,进行使用自增长位作为查询条件
例如:在TableA中AA项为自增长项,这样数据库本身已经对它建有index。使用它作为查询条件就会比使用AB,AC项更加快。
还有,在为AA项限制条件时,不要使用like ‘%1’这些后匹配方式;尽量使用between ... and ...或者< >的匹配方式
3.如果无法去掉的循环,都要尽量减少循环中的游标,不要循环中嵌套循环
例如,对于一些基础表,如TableA,需要添加90万的数据量。就只是使用一个游标进行循环插入,且循环中执行的语句也只是insert数据的语句,不要掺杂其他复杂的运算或者再嵌套循环
根据开发人员的建议,我重新修改了sql,将中间的循环去掉,尽量多地使用数据集的方式来插入数据。
sql生成数据的效率得到了飞速地提高,原先2天无法加完的数据,一个晚上就搞掂了。
效率是提高了,但是数据中的内容就会变得相对集中,例如有10几万的数据都是同一时刻,同一个操作用户生成的。这样的话,对于一些查询就非常不利了。因为有可能一次需要查询出几十万的数据,这样是也不符合现实情况。
于是,对于这种情况,我们需要针对不同的场景,对数据进行微调。例如使用循环,将数据的udpatetime,或者updateguy进行随机更新。
这样就又保证了数据量,也保证了数据的真实性。