背景:
公司的自研产品准备替换外购的产品,涉及到的数据量达到几亿,供应商推送数据采用推送到他们的OSS上面,给我们开放一个子账号用来读取数据文件。但是怎么快速的将数据文件里的数据导入到我们mysql的库中,是个难题,用程序来跑,计算下来要跑两个月且优化空间不大。
数据文件有以下特征:
- 供应商给的数据文件间隔符还不是逗号,而是制表符’/u0001’
- 数据文件一般在500M左右,总计有1000多个
解决:
很多数据库工具都带有导入文件的功能,少量的数据文件可以采用这种方式
比如navicate可以导入数据文件,csv文件可以当text文件导入,这样的好处是可以自己设置分割符,但是一次只能选中一个CSV文件,如果数据文件很多,真的是很折磨人,效率极低。
使用MYSQL的LOADFILE功能,可以快速的写入数据
mysql的load file命令,可以读取客户端的数据文件,而且读写速度很快,最好硬盘是固态的,这样效率更高,经过测试,300万的数据20S就可以写进去。如果文件命令是有规则的,写个代码生成一下批量执行脚本就OK了。LOADFILE脚本如下:
-- 数据文件的位置
LOAD DATA LOCAL INFILE 'D:\\scrm\\5eb696d75372c45ec22d9136\\bdMemberEventLog\\20240507\\part-00000-e90f623c-67bf-437c-8e72-5f6f8a894b85-c000.csv'
-- 要写入的目标表
INTO TABLE MEMBER_EVENT_LOG
-- 间隔符
FIELDS TERMINATED BY ''
ENCLOSED BY '"'
ESCAPED BY ''
-- 换行符
LINES TERMINATED BY '\n'
-- csv文件的目标字段,这里取值是按顺序的
IGNORE 1 LINES
(@accountId,@channelId,@clientId, @createdAt,@id,@isSystem,@memberId,@name,@occurredAt,@openId,@properties,@unionId,@uniqueId,@updatedAt
)
SET
-- 写入表中的字段account_id=@accountId,channel_id=@channelId,member_id=@memberId,open_id=@openId,union_id= @unionId,client_id=@clientId,name=@name,properties=@properties,unique_id=@uniqueId,is_system=@isSystem,occurred_at=CASE WHEN @occurredAt = '' OR @occurredAt IS NULL THEN NULL ELSE @occurredAtEND,created_at=CASE WHEN @createdAt = '' OR @createdAt IS NULL THEN NULL ELSE @createdAt END,updated_at=CASE WHEN @updatedAt = '' OR @updatedAt IS NULL THEN NULL ELSE @updatedAtEND,qm_id=@id,
file_name ='D:\\scrm\\5eb696d75372c45ec22d9136\\bdMemberEventLog\\20240507\\part-00000-e90f623c-67bf-437c-8e72-5f6f8a894b85-c000.csv';
注意:
如果遇到不能读取本地文件的报错,可以执行命令 SET GLOBAL local_infile = 1
; 这样就可以读取本地文件了