基于python实现对MYSQL快速插入千万级数据,本次只针对MYSQL数据库进行阐述。
在软件性能测试过程中,我们需要向数据库中预制大量测试数据,那么怎么预制呢?
预制数据即向数据库中插入数据,常用的格式如下:
Insert into表名称(列1,列2,……) values(值1,值2,……);
那么怎么控制insert数量呢?最不切实际的方法就是每一条记录对应一条insert语句,然后一条一条批量执行,如果数据量超大,这样做肯定不可取,或许会想到MYSQL中有存储过程可以来实现,如下:
1.创建存储过程
qqcreate procedureinsertProc(count int)
declare @变量1 int
declare @变量2 nvarchar(20)
declare @变量3 varchar(20)
declare @变量n varchar(20)
set @变量1=1
set @变量2=2
set @变量3=3
set @变量n=n
while(变量1
begin
set 变量1=变量1+1
insert into 表名(列1,列2,列3,列n) values(变量1,变量2,变量3,变量n)
end
2.执行存储过程
callinsertPrc(10000) //插入10000行
方法优缺点分析:此种方法实现简单,数据量在万条以内推荐使用,但是如果达到百万甚至千万级别,插入时间会太长,测试过程中如果需要经常换数据,会导致我们的测试效率低下,每次预制可能需要几十分钟甚至几个小时,曾经尝试过1000万条数据插入需要1个小时左右,当然服务器配置不一样,可能有差别。
问题描述:那么我们想在几分钟内完成千万级数的插入,怎么实现呢?
解决思路:首先我们想下,如果提高多点并发插入肯定会提高每秒数据处理的数量,例如通过多线程方式向MYSQL数据库中插入数据,可以通过编写一个多线程客户端方式来实现数据插入,这样一来实现门槛高,成本高,可能还达不到预期。
我们还是从MYSQL本身出发,分析MYSQL有没有其它的方式来添加数据,这里推荐一种高效插入数据的方法,MYSQL的load文件方式来插入数据,该方法可以从文件中读取每一行,然后直接装入一个表中,基本语法如下:
LOAD DATA[LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE '文本文件'
[REPLACE| IGNORE]
INTOTABLE 表名
[FIELDS
[TERMINATEDBY 'string']
[[OPTIONALLY]ENCLOSED BY 'char']
[ESCAPEDBY 'char' ]
]
[LINES
[STARTINGBY 'string']
[TERMINATEDBY 'string']
]
[IGNOREnumber LINES]
[(col_name_or_user_var,...)]
[SETcol_name = expr,...)]
重要参数说明:
LOW_PRIORITY:如果参数指定了该值,则在执行load操作时MYSQL需要等该表没有其它用户请求操作时才把数据插入。
CONCURRENT:如果参数指定了该值,则在load操作时,如果有其它用户请求时则开启新的线程来获取数据。
LOCAL:指定该值可以在客户端load文件,也可以在服务端load文件,如果没有该值只能把文件放到服务器端进行load操作。
REPLACE:指定该值后,如果导入过程中存在重复数据会进行替换,如果不指定则遇到重复数据会报错
IGNORE:指定该值后,如果导入过程中存在重复数据则会忽略,跳过这一条数据,如果不指定则遇到重复数据会报错。
FIELDS:指定文本每一行内部的分隔符
TERMINATED BY:用于指定每一行的分隔符,比如逗号分隔
ENCLOSED BY:用于控制字段的引号,必须为单一字符,如果不指定参数OPTIONALLY,则所有的字段都被包含在ENCLOSED BY字符串中,如果指定了OPTINALLY,则只包含指定的字符在ENCLOSED BY字符串中。
LINES:指定文本每一行的开始和结束的分隔符
STARTINGBY:每一行的起始符号
TERMINATEDBY:每一行的结束符号
举例说明::
1. 例如我们需要向一个用户表(t_user)中load三条数据,假设数据和格式如下:
>1,张三,男,18,北京,18600000001
>2,李四,女,19,上海,18600000002
>3,王五,男,20,深圳,18600000003
将上面三条数据放入D:\\share\\insertUserInfo.txt文件中,注意脚本中路径必须为\\(两个\)
2. Load脚本如下:
LOAD DATA INFILE'D:\\share\\insertUserInfo.txt' INTO TABLE t_user
FIELDS
TERMINATED BY '\,'
OPTIONALLY ENCLOSED BY '\"'
LINES
STARTING BY '\>'
TERMINATED BY '\n';
3.测试结果如下:
3.1在控制台中登陆MYSQL后切换到对应数据库,进行执行如下:
3.2 查询结果
那么问题又来了,当数据量达到1000万时,怎么生成数据,以及把数据放到文件中进行保存?当然是需要用程序脚本来完成,基本思路如下:
1,生成格式数据
2,将数据保存在文件中,注意脚本中的编码格式必须和数据库中数据库名以及表名一致,如果不一致中文插入会失败也可能出现乱码。
脚本实现如下:
#encoding=utf-8
importrandom
#定义数据量
count=10000000
#打开文件,并动态生成数据,将数据存在文件中
try:
f =file("d:\\share\\insertUserInfo.txt","wb")
for i in range(1,count+1):
#定义数据,以下只是测试数据,可以根据自己的业务通过调用函数去随机生成对应的值
id = str(i) name=''.join(random.sample('zyxwvutsrqponmlkjihgfedcba',4)).replace('','')
sex=str(random.choice(['男', '女']))
age=str(random.randrange(10, 99))
address=str(random.choice(['北京', '上海','深圳','广州','杭州']))
telephone=str(random.choice(['186000000001','186000000002','186000000003']))
userInfo = '>'+id+','+name+','+sex+','+age+','+address+','+telephone+'\n'
f.write(userInfo)
exceptException,e:
print Exception,":",e
finally:
f.close()
执行结果展示(才耗时37秒,当然这个时间还得看具体的每一条数据量,这里测试的每一条数据相对较少):
总结:MYSQL中load方法高效便捷加上python以辅助,两者相辅相成,很快就完成了千万级数据预制,在测试过程中提高了很大效率。
当然python作为一门脚本语言,功能非常强大,亦可直接操作数据库表,在数据量小的情况下直接操作数据库,不通过中间文件这样更加节省时间。