【问题标题】:How to import a large csv into a mysql with java using prepared statements and batch如何使用准备好的语句和批处理将大型 csv 导入到带有 java 的 mysql 中
【发布时间】:2019-08-09 13:06:12
【问题描述】:

这里我有一个代码块,它将插入一个名为 Earnings 的表中,并将为 csv 的每一行使用准备好的语句来处理 4 个整数,并将它们添加到一个批处理中,并在读取所有行时执行该批处理。为什么这会在 csv 文件的第 2009 行开始插入,换句话说,它似乎不稳定,并且只会将部分 csv 导入 mysql 表,如何使用 6530 行 csv 提高批处理执行效率?另外我如何处理一个不存在的准备好的语句,比如在准备好的语句的参数索引 4 处有一个 int 或者可能为空。

statement.executeUpdate("CREATE TABLE Earnings("
                    + "tournament INT references Tournaments( tournament_id ), "
                    + "player INT references Players( player_id ), "
                    + "prize_money INT, "
                    + "position INT, "
                    + "PRIMARY KEY(tournament, player))");
Statement statement = conn.createStatement();
try{
                String insertTableSQL2 = "INSERT INTO Earnings"
                        + "(tournament, player, prize_money, position) VALUES"
                        + "(?,?,?,?)";
                PreparedStatement preparedStatement2 = conn.prepareStatement(insertTableSQL2);
                BufferedReader reader2 = new BufferedReader(new FileReader("earnings.csv"));
                String line = null; //line read from csv
                Scanner scanner = null; //scanned line
                while ((line = reader2.readLine()) != null) {

                    scanner = new Scanner(line);
                    scanner.useDelimiter(",");

                        while (scanner.hasNext()) {
                            String str = scanner.next();
                            preparedStatement2.setInt(1, Integer.parseInt(str));
                            String str2 = scanner.next();
                            preparedStatement2.setInt(2, Integer.parseInt(str2));
                            String str3 = scanner.next();
                            preparedStatement2.setInt(3, Integer.parseInt(str3));
                            String str4 = scanner.next();
                            preparedStatement2.setInt(4, Integer.parseInt(str4));
                            preparedStatement2.addBatch();
                        }


                }
                preparedStatement2.executeBatch();
                preparedStatement2.close();
                scanner.close();
                reader2.close(); //closing CSV reader
            }
            catch(Exception e){
                e.printStackTrace();
            }
            System.out.println("earnings.csv imported");

csv 格式如下:

19367,26,677,1
19367,112,271,2
19372,51,134,1
19382,213,150,1
19382,243,50,2
18446,34,2976,1
18446,111,1082,2
19452,28,135,1

【问题讨论】:

    标签: java mysql csv prepared-statement batch-processing


    【解决方案1】:

    使用 LOAD DATA INFILE 语法。如果您使用它,那将更快,也无需编写所有这些代码行。

    查看here

    【讨论】:

    • 我之前试过,它说 MySQL 服务器正在运行 --secure-file-priv 选项,所以它不能执行这个语句
    • 尝试解决该问题,然后您将获得更有效的方法来做同样的事情。检查这个答案stackoverflow.com/questions/32737478/…
    【解决方案2】:

    您可以将库 com.opencsv.CSVReader 用作 CSV 读取器/写入器。 并编写简单的代码逐行读取 CSV 文件并构造 SQL 查询,然后执行查询。

    public void loadCSVfile() {
            try (CSVReader reader = new CSVReader(new FileReader("earnings.csv"), ',');
                 Connection connection = DBConnection.getConnection();) {
                String insertQuery = "Insert into Earnings (tournament, player, prize_money, position) values (null,?,?,?)";
                PreparedStatement pstmt = connection.prepareStatement(insertQuery);
                String[] rowData = null;
                int i = 0;
                while ((rowData = reader.readNext()) != null) {
                    for (String data : rowData) {
                        pstmt.setString(i++, data);
                        pstmt.addBatch();
                        pstmt.executeBatch();
                    }
                    i = 0;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    

    如果可能,或者使用 MySQL 命令加载:

    public void loadCSV()
        {
            try (Connection connection = DBConnection.getConnection()) {
                String sqlQuery = "LOAD DATA LOCAL INFILE '" + "earnings.csv" + "' INTO TABLE Earnings FIELDS TERMINATED BY ','" + " LINES TERMINATED BY '\n' (tournament, player, prize_money, position) ";
                Statement stmt = connection.createStatement();
                stmt.execute(sqlQuery);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2015-10-12
      • 1970-01-01
      • 2018-10-27
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 2012-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多