【问题标题】:MySQL, Most efficient Way to Load Data from a parsed fileMySQL,从已解析文件中加载数据的最有效方式
【发布时间】:2012-09-29 23:26:57
【问题描述】:

我的文件格式如下:

Table1; Info
rec_x11;rec_x21;rec_x31;rec_x41
rec_x12;rec_x22;rec_x32;rec_x42
...
\n
Table2; Info
rec_x11;rec_x21;rec_x31;rec_x41
rec_x12;rec_x22;rec_x32;rec_x42
...
\n
Table3; Info
rec_x11;rec_x21;rec_x31;rec_x41
rec_x12;rec_x22;rec_x32;rec_x42
...

每批记录从 TableX 标头之后的下一行开始,以空行分隔符结束,大小约为 700-800 行。

每批这样的行(rec_xyz...)都需要导入到批头(TableX)中指明的相关MyISAM表名中

我熟悉使用 shell 命令将流传输到 LOAD DATA 命令的选项。

我对简单的 java snipet 代码很感兴趣,它会解析这个文件并每次为一批记录执行 LOAD DATA(在 for 循环中,可能使用 seek 命令)。

现在我正在尝试使用 IGNORE LINES 来跳过已处理的记录,但我不熟悉是否可以选择忽略 BELOW 中的行?

有没有更有效的方法来解析这种类型的文件并将其加载到 DB 中?

编辑

我已经读到 JDBC 从 5.1.3 开始支持到 LOAD DATA 的输入流,我可以使用它通过输入流迭代文件并每次更改 LOAD DATA 语句吗?

【问题讨论】:

  • 您能否对每个要添加到另一个LOAD DATA 命令的表进行搜索和替换?

标签: java mysql csv load-data-infile


【解决方案1】:

我附上我的代码作为解决方案,

此解决方案基于 MySQL Connector/J 5.1.3 及更高版本添加的additional functionality (setLocalInfileInputStream)。

我将输入流管道化到 LOAD DATA INTO 语句中,而不是使用直接文件 URL。

附加信息:我使用 BoneCP 作为连接池

public final void readFile(final String path)
        throws IOException, SQLException, InterruptedException {
    File file = new File(path);

    final Connection connection = getSqlDataSource().getConnection();
    Statement statement = SqlDataSource.getInternalStatement(connection.createStatement());

    try{
        Scanner fileScanner = new Scanner(file);
        fileScanner.useDelimiter(Pattern.compile("^$", Pattern.MULTILINE));

        while(fileScanner.hasNext()){
            String line;
            while ((line = fileScanner.nextLine()).isEmpty());

            InputStream is = new ByteArrayInputStream(fileScanner.next().getBytes("UTF-8"));
            String [] tableName = line.split(getSeparator());
            setTable((tableName[0]+"_"+tableName[1]).replace('-', '_'));

            String sql = "LOAD DATA LOCAL INFILE '" + SingleCsvImportBean.getOsDependantFileName(file) + "' " 
                    + "INTO TABLE " + SqlUtils.escape(getTable()) 
                    + "FIELDS TERMINATED BY '" + getSeparator() 
                    + "' ESCAPED BY '' LINES TERMINATED BY '" + getLinefeed() + "' ";
            sql += "(" + implodeStringArray(getFields(), ", ") + ")";       
            sql += getSetClause();

            ((com.mysql.jdbc.Statement) statement).setLocalInfileInputStream(is);
            statement.execute(sql);         
        }
    }finally{
        statement.close();
        connection.close();
    }   
}

【讨论】:

  • 参考stackoverflow.com/questions/34826934/… 然而,如果我的数据库在 Linux 上并且我的 Java 代码在 Windows 上运行,那么我的问题是相同的,然后文件中的加载数据查询失败,任何替代方案吗?
猜你喜欢
  • 1970-01-01
  • 2013-03-23
  • 2017-09-12
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
  • 2014-06-02
相关资源
最近更新 更多