如何将大文件快速入库?
在开发过程中,往往会有大数据量的文件需要做入库处理,这些文件少则几百兆,多则几十G. 如果处理方法不得当,会浪费你大量的时间和精力,甚至做无用功。
入库需要考虑的问题
- 对原有数据是否有影响,比如数据重复导致唯一性问题。
- 是否需要生成主键,需要通过算法生成主键,这种方式只能通过程序读取文件。
- 原始数据是否需要经过处理才能入库。
文件的准备操作
-
如果文件能通过简单命令处理就能入库,那么久没必要使用程序处理。
比如需要将文件某一个字段的值中的
:
替换为空字符串。通过一个批处理命令就可以办到了。 -
如果文件是大量的小文件,可以先将文件合成一个文件。比如:a.txt、b.txt、c.txt 三个小文件。
# 合并后缀为.txt的文件到 all.txt cat *.txt > all.txt
-
如果文件太大,也可考虑将文件分割成大小相同或者行数相同的一些列小文件,这样方便单个处理。比如有文件:single.txt,根据行数进行分割。分割后生成new_01,new _02.....
#查看文件行数 wc -l single.txt #按每个文件100000行进行分割,-a 指定分割后生成的文件编号的位数,-d 表示使用数字编号 split -a 2 -l 100000 -d single.txt new_ #统一给文件加上后缀(在分割生成的目录下执行) for file in *;\ do mv "$file" "$file.txt";\ done
数据库的准备工作
-
如果导入数据没用到自增主键,那么尽可能取消掉主键约束。
可以在读取文件的程序中使用主键自增算法(zk自增ID,snowflake算法),这样可以避免主键重复。待文件导入后在加上主键约束。
-
尽可能取消掉字段的唯一索引,唯一索引每次插入会去检查字段的唯一性。
对于需要去重的字段、建议在所有数据都入库完成后进行去重。在程序中去重没有意义(文件太大),查询判断存在与否,对插入的效率影响极大。 数据的去重可以参照我的去重小案例
-
可以将要操作的表的引更换为MyISAM,导入完成后切换回Innodb
#切换为MyIsam引擎 ALTER TABLE 表明 ENGINE=MyISAM; #切换为InnoDb ALTER TABLE 表明 ENGINE=Innodb;
入库工作
-
不需要通过程序处理即可入库的文件(字段完美契合需求、不用生成主键)
步骤一:如果有多个小文件可以使用
cat命令
将文件合并成一个,对文件中要替换的符号进行处理。步骤二:将文件复制到MySql的安装机器上(也可以通过Navicat 来导入本地的文件)。
步骤三:登录到MySql,使用
load data infile
命令来导入数据。使用命令时注意文件中的特殊字符和分割的的冲突。步骤四:切换数据表的存储引擎,去除重复的字段。添加主键约束、添加索引。
-
需要对文件的字段进行程序处理或者通过算法生成主键。
这种方式入库需要考虑文件过大造成OOM问题,所以一般都会对大文件进行split分割,然后单独处理多个小文件。这个时候又要考虑效率问题了,如何高效的对多个文件进行处理。可以使用多线程并行的对多个文件进行读取、然后使用批处理的方式插入数据库(批插入的效率很高)。
步骤一:使用split命令对文件进行均匀分割处理,对文件中要替换的符号进行处理。
步骤二:使用多任务并行的方式进行读取,比如有文件new_01——new_100,可以使用10个线程,每个线程循环读完10个文件,每次读取1w条后批量插入到数据库。并行方式很多比如Fork/Join,最简单的就是使用Thread 的 join()方法 来实现并行。这样会极大的提高读取和写入效率。一般1G的文件几分钟就插入完了。
步骤四:切换数据表的存储引擎,去除重复的字段。添加主键约束、添加索引。