首页 > 解决方案 > 从具有 3000000 行的表的 Java 中读取行

问题描述

我想读取具有 30000000 行的表的行。我曾经st.setFetchSize(10000)以为我会在 10000 个包中获得 30000000 行,但我只获得前 10000 行并且程序结束。请谁能告诉我如何在 10000 个包装中获得所有 30000000 行?

public class InsertBatch {
    public static void main(String[] args) throws SQLException {
        try (Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgres", "postgres", "root")) {
            connection.setAutoCommit(false);
            Statement st = connection.createStatement(
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY,
                ResultSet.FETCH_FORWARD
            );
            System.out.println(new Date());
            st.setFetchSize(10000);
            System.out.println("start query ");
            ResultSet rs = st.executeQuery("SELECT * FROM contratacion");
            System.out.println("done query ");
            String insert = "INSERT INTO contrato(contrato, codigo_postal,cups) VALUES(?, ?, ?)\n" +
            "ON CONFLICT (contrato) DO\n" +
            "UPDATE SET codigo_postal = excluded.codigo_postal, cups = excluded.cups";
            PreparedStatement pst = connection.prepareStatement(insert);
            int cont = 0;
            while(rs.next()) {
                cont++;
                Integer contrato  = rs.getInt(1);
                Integer codigo_postal  = rs.getInt(2);
                String cups  = rs.getString(3);

                pst.setInt(1, contrato);
                pst.setInt(2, codigo_postal);
                pst.setString(3, cups);
                pst.executeUpdate();
                connection.commit();
                System.out.println(cont);
            }
            System.out.println(new Date());
        } catch (SQLException ex) {
        }
    }
}

标签: javasqlpostgresqljdbc

解决方案


阅读文档,即 javadoc createStatement​(int resultSetType, int resultSetConcurrency, int resultSetHoldability)

参数:

resultSetType- 以下ResultSet常数之一:ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, 或ResultSet.TYPE_SCROLL_SENSITIVE

resultSetConcurrency- 以下ResultSet常数之一:ResultSet.CONCUR_READ_ONLYResultSet.CONCUR_UPDATABLE

resultSetHoldability- 以下ResultSet常数之一:ResultSet.HOLD_CURSORS_OVER_COMMITResultSet.CLOSE_CURSORS_AT_COMMIT

你的代码是:

Statement st = connection.createStatement(
                  ResultSet.TYPE_FORWARD_ONLY, // Good
                  ResultSet.CONCUR_READ_ONLY,  // Good
                  ResultSet.FETCH_FORWARD      // BAD !!!!!
               );

如您所见,第三个参数不是有效值之一。

由于您connection.commit();while(rs.next())循环内调用,因此如果您通过ResultSet.HOLD_CURSORS_OVER_COMMIT.


当然,您甚至不应该这样做,因为 3000000 条INSERT语句将永远持续下去,特别是如果您单独提交每条语句。哎呀!

如果必须,因为需要在 Java 中处理数据,至少使用批处理

相反,只需将其编写为单个语句:

INSERT INTO contrato ( contrato, codigo_postal, cups )
SELECT contrato, codigo_postal, cups
FROM contratacion
ON CONFLICT (contrato) DO UPDATE
SET codigo_postal = excluded.codigo_postal
  , cups = excluded.cups

推荐阅读