java - 具有限制行数的结果集 jdbc 驱动程序

标签 java jdbc

我正在尝试创建一个批处理程序。问题是表可能有 200 万行,这可能会产生内存问题。在我的工作中,我使用 DB2,在家里测试时我使用 mysql。

我已经用 eclipse 进行了调试,并且我发现结果集包含所有行。

我在网页中搜索过,但没有找到解决方案。比如我的测试代码是:

    package misCodigos;

    import java.io.FileWriter;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;

    public class testLimitDB {

        // JDBC driver name and database URL
        static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
        static final String DB_URL = "jdbc:mysql://localhost/testing";

        //  Database credentials
        static final String USER = "root";
        static final String PASS = "8182";


        private static FileWriter fw=null;

        public static void main(String[] args) {
            // Clase que pretende mostrar cómo insertar filas en java
            Connection conn = null;
            Statement stmt = null;


            try{

                //STEP 2: Register JDBC driver
                Class.forName("com.mysql.jdbc.Driver");

                //STEP 3: Open a connection
                System.out.println("Connecting to database...");
                conn = DriverManager.getConnection(DB_URL,USER,PASS);

                //STEP 4: Execute a query
                //  System.out.println("Creating statement...");
                stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                        java.sql.ResultSet.CONCUR_READ_ONLY);
                String sql = "select * from tablaTest";


                PreparedStatement pstmt;
                pstmt = conn.prepareStatement(sql);

                conn.setAutoCommit(false);
                pstmt.setFetchSize(200);

                ResultSet rs = pstmt.executeQuery(sql);
                System.out.println("Starting to retrieve data. Memory Used: " + getUsedMemorySize());

                //System.out.println(rs.getString(rs.last()));

                /*          rs.last(); 
                int numRows = rs.getRow(); 
                System.out.println("Numero de filas: " + numRows);*/

                fw = new FileWriter("test.out");
                while (rs.next()) {
                    fw.write(rs.getInt(1) + ";" + rs.getString(2) + "\n");
                }
                System.out.println("Done retrieving data => Memory Used: "  + getUsedMemorySize());

                pstmt.close();
                conn.close();
                fw.flush();
                fw.close();

            }catch(Exception e){
                //Handle errors for Class.forName
                e.printStackTrace();
            }finally{
                //finally block used to close resources

                try{

                    if (fw != null){
                        fw.flush();
                        fw.close();      
                    }

                    if(stmt!=null) {
                        stmt.close();
                    }
                }catch(SQLException | IOException se2){
                }// nothing we can do
                try{
                    if(conn!=null) {
                        conn.close();
                    }
                }catch(SQLException se){
                    se.printStackTrace();
                }//end finally try
            }//end try
            System.out.println("Finalizado!");


        }

        public static long getUsedMemorySize() {

            long freeSize = 0L;
            long totalSize = 0L;
            long usedSize = -1L;
            try {
                Runtime info = Runtime.getRuntime();
                freeSize = info.freeMemory();
                totalSize = info.totalMemory();
                usedSize = totalSize - freeSize;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return usedSize;

        }

    }

Could anyone help me?

谢谢

PD:我创建了 db2 的代码。我不确定结果集是否只获取我喜欢的行,因为我在 Eclipse 和结果集变量中使用 Debug模式启动,现在它非常不同,并且看起来是加密的。

import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class testLimitDB {

    // JDBC driver name and database URL
    //static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  

    static final String JDBC_DRIVER = "com.ibm.db2.jcc.DB2Driver";  
    //static final String DB_URL = "jdbc:mysql://localhost/testing";
    static final String DB_URL = "jdbc:db2://localhost:50000/SAMPLE";

    //  Database credentials MYSQL
    //static final String USER = "root";

    static final String USER = "db2admin";
    static final String PASS = "8182";


    private static FileWriter fw=null;

    public static void main(String[] args) {
        // Clase que pretende mostrar cómo insertar filas en java

        Connection conn = null;
        Statement stmt = null;


        try{

            //STEP 2: Register JDBC driver
            Class.forName(JDBC_DRIVER);

            //STEP 3: Open a connection
            System.out.println("Connecting to database...");
            conn = DriverManager.getConnection(DB_URL,USER,PASS);

            //STEP 4: Execute a query
            //  System.out.println("Creating statement...");
            stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                    java.sql.ResultSet.CONCUR_READ_ONLY);
            String sql = "select * from FELIPE.TABLATEST";


            PreparedStatement pstmt;
            pstmt = conn.prepareStatement(sql);

            conn.setAutoCommit(false);
            pstmt.setFetchSize(999);

            ResultSet rs = pstmt.executeQuery();
            System.out.println("Starting to retrieve data. Memory Used: " + getUsedMemorySize());

            //System.out.println(rs.getString(rs.last()));

            /*          rs.last(); 
            int numRows = rs.getRow(); 
            System.out.println("Numero de filas: " + numRows);*/

            fw = new FileWriter("test.out");
            while (rs.next()) {
                fw.write(rs.getInt(1) + ";" + rs.getString(2) + "\n");
            }
            System.out.println("Done retrieving data => Memory Used: "  + getUsedMemorySize());

            pstmt.close();
            conn.close();
            fw.flush();
            fw.close();

        }catch(Exception e){
            //Handle errors for Class.forName
            e.printStackTrace();
        }finally{
            //finally block used to close resources

            try{

                if (fw != null){
                    fw.flush();
                    fw.close();      
                }

                if(stmt!=null) {
                    stmt.close();
                }
            }catch(SQLException | IOException se2){
            }// nothing we can do
            try{
                if(conn!=null) {
                    conn.close();
                }
            }catch(SQLException se){
                se.printStackTrace();
            }//end finally try
        }//end try
        System.out.println("Finalizado!");


    }

    public static long getUsedMemorySize() {

        long freeSize = 0L;
        long totalSize = 0L;
        long usedSize = -1L;
        try {
            Runtime info = Runtime.getRuntime();
            freeSize = info.freeMemory();
            totalSize = info.totalMemory();
            usedSize = totalSize - freeSize;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return usedSize;

    }

}

我再次尝试,我的结论是驱动程序(mysql 和 db2)工作正常。我用jvisualvm进行了测试,我清楚地看到内存随着光标的大小而变化。我会写一份有不同结论的文件,然后将其发布。

最佳答案

我认为您的问题来自于使用没有服务器端游标的 MySQL 进行测试,并且无论您是否设置 FETCH 大小,选择大结果集都不可避免地会导致 OOM。

由于游标,DB2 不会出现同样的问题,并且驱动程序不会抛出 OOM。您需要定义一个非常适合的获取大小。如果您有大量工作,我会使用一个大值。换句话说,当您针对相同的环境进行测试时:)

关于java - 具有限制行数的结果集 jdbc 驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36249224/

相关文章:

java - 将方法绑定(bind)到android中的按钮

java - 按下后退按钮时如何保存状态

java - 无法找到对此进行冗余空检查的原因,该检查已知为非空

java - 如何使用 JDBC 来最大化 Netty 的性能?

java - 识别 JDBC 中的executeBatch()失败

Java 检查 HttpResponse 是否仍然存在

java - Android:编辑以编程方式添加的 View

java - 在 jdbc 应用程序中连接 mysql 服务器的正确方法是什么?

java - 如何获得外键实际值发生变化的数据库 View ?

java - 使用 JDBC 插入 PostgreSQL 时间类型时出错