Java 具有限制行数的结果集jdbc驱动程序
我正在尝试创建一个批处理程序。问题是表可能有200万行,这可能会产生内存问题。在我的工作中,我使用DB2,在家中测试时,我使用mysql 我已经用eclipse进行了调试,并且查看了resultset包含所有行的情况 我在网页上搜索过,但没有找到解决方案。例如,我的测试代码是:Java 具有限制行数的结果集jdbc驱动程序,java,jdbc,Java,Jdbc,我正在尝试创建一个批处理程序。问题是表可能有200万行,这可能会产生内存问题。在我的工作中,我使用DB2,在家中测试时,我使用mysql 我已经用eclipse进行了调试,并且查看了resultset包含所有行的情况 我在网页上搜索过,但没有找到解决方案。例如,我的测试代码是: package misCodigos; import java.io.FileWriter; import java.io.IOException; import java.sql.Co
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的代码。我不确定resultset是否只获取我喜欢的行,因为我在eclipse中使用了debug模式和resultset变量,现在它非常不同,并且看起来是加密的
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进行测试,而选择较大的结果集不可避免地会导致OOM,无论您是否设置了FETCH size
DB2没有同样的问题,因为游标和驱动程序不会抛出OOM。您需要定义一个非常适合的获取大小。如果你有一个大批量的工作,我会使用一个大的价值。换句话说,当您在同一环境下进行测试时:)讨论如何在db2中进行测试。MySQL的可能重复使用“LIMIT”,您需要获取整个表的信息文件,还是只需要N行?Sasha,我需要获取整个表。谢谢Alexandre!我将尝试在DB2中进行测试,并会让您知道。:)Alexandre,我不确定行为是否正确,因为结果集非常不同,mysql和所有字段都是字母,没有意义。我想如果它用mysql抛出OOM,而用DB2抛出OOM,至少应该修复OOM异常。另一方面,如果您想100%确定它是如何工作的,您可以使用一个用于DB2 SQL监控的程序,例如QueryMonitor。在那里,您可以观察SQL是如何执行的。或者,您可以嗅探网络通信量,以查看完成了多少远程调用,这是如果您想验证获取大小。BHi Alexandre,我再次尝试,我的结论是驱动程序(mysql和db2)工作正常。我使用jvisualvm进行了测试,我清楚地看到内存随着光标的大小而变化。