如何将大文件快速入库?

如何将大文件快速入库?

在开发过程中,往往会有大数据量的文件需要做入库处理,这些文件少则几百兆,多则几十G. 如果处理方法不得当,会浪费你大量的时间和精力,甚至做无用功。

入库需要考虑的问题

  1. 对原有数据是否有影响,比如数据重复导致唯一性问题。
  2. 是否需要生成主键,需要通过算法生成主键,这种方式只能通过程序读取文件。
  3. 原始数据是否需要经过处理才能入库。

文件的准备操作

  1. 如果文件能通过简单命令处理就能入库,那么久没必要使用程序处理。

    比如需要将文件某一个字段的值中的 替换为空字符串。通过一个批处理命令就可以办到了。

  2. 如果文件是大量的小文件,可以先将文件合成一个文件。比如:a.txt、b.txt、c.txt 三个小文件。

    # 合并后缀为.txt的文件到 all.txt
    cat *.txt > all.txt
    
  3. 如果文件太大,也可考虑将文件分割成大小相同或者行数相同的一些列小文件,这样方便单个处理。比如有文件: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
    
    
    

数据库的准备工作

  1. 如果导入数据没用到自增主键,那么尽可能取消掉主键约束。

    可以在读取文件的程序中使用主键自增算法(zk自增ID,snowflake算法),这样可以避免主键重复。待文件导入后在加上主键约束。

  2. 尽可能取消掉字段的唯一索引,唯一索引每次插入会去检查字段的唯一性。

    对于需要去重的字段、建议在所有数据都入库完成后进行去重。在程序中去重没有意义(文件太大),查询判断存在与否,对插入的效率影响极大。 数据的去重可以参照我的去重小案例

  3. 可以将要操作的表的引更换为MyISAM,导入完成后切换回Innodb

    #切换为MyIsam引擎
    ALTER TABLE 表明 ENGINE=MyISAM;
    #切换为InnoDb
    ALTER TABLE 表明 ENGINE=Innodb;
    

入库工作

  1. 不需要通过程序处理即可入库的文件(字段完美契合需求、不用生成主键)

    步骤一:如果有多个小文件可以使用cat命令将文件合并成一个,对文件中要替换的符号进行处理。

    步骤二:将文件复制到MySql的安装机器上(也可以通过Navicat 来导入本地的文件)。

    步骤三:登录到MySql,使用load data infile 命令来导入数据。使用命令时注意文件中的特殊字符和分割的的冲突。

    步骤四:切换数据表的存储引擎,去除重复的字段。添加主键约束、添加索引。

  2. 需要对文件的字段进行程序处理或者通过算法生成主键。

    这种方式入库需要考虑文件过大造成OOM问题,所以一般都会对大文件进行split分割,然后单独处理多个小文件。这个时候又要考虑效率问题了,如何高效的对多个文件进行处理。可以使用多线程并行的对多个文件进行读取、然后使用批处理的方式插入数据库(批插入的效率很高)。

    步骤一:使用split命令对文件进行均匀分割处理,对文件中要替换的符号进行处理。

    步骤二:使用多任务并行的方式进行读取,比如有文件new_01——new_100,可以使用10个线程,每个线程循环读完10个文件,每次读取1w条后批量插入到数据库。并行方式很多比如Fork/Join,最简单的就是使用Thread 的 join()方法 来实现并行。这样会极大的提高读取和写入效率。一般1G的文件几分钟就插入完了。

    步骤四:切换数据表的存储引擎,去除重复的字段。添加主键约束、添加索引。

    原文作者:始终我是我
    原文地址: https://www.jianshu.com/p/bf737833d198
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞