我正在将数据库从Java DB复制到MySQL。所有表都在MySql中正确设置,我编写了一个复制数据库的方法。
方法中没有错误,它适用于大小有限的表格。但是对于大型桌来说它太慢了。复制7937记录花了大约5分29秒!由于一张表有230万条记录,我不得不等待超过26小时......
我在Netbeans中运行它,我的输出在这里:(批量大小= 2000)
run: ------ Copying table currency ------ 26 rows needs to be copied Executed batch for currency, inserted the last 26 elements ------ Finished copying table currency ------ ------ Copying table exchange ------ 31 rows needs to be copied Executed batch for exchange, inserted the last 31 elements ------ Finished copying table exchange ------ ------ Copying table markets ------ 82 rows needs to be copied Executed batch for markets, inserted the last 82 elements ------ Finished copying table markets ------ ------ Copying table trade ------ 2303371 rows needs to be copied Executed batch for trade, inserted 2000 elements Have copied a total of 2000/2303371 rows, 0% Executed batch for trade, inserted 2000 elements Have copied a total of 4000/2303371 rows, 0% Executed batch for trade, inserted 2000 elements Have copied a total of 6000/2303371 rows, 0% BUILD STOPPED (total time: 5 minutes 29 seconds)
所以当我看到这需要比预期更长的时间时,我停止了执行。
/** * * @param javadb Connection to the source database * @param mysql Connection the target database * @param orderedTables table names in the order they are to be copied (so no foreign key constraints error stuff happens) */ public static void copyFromJavaDBtoMySQL(Connection javadb, Connection mysql, String[] orderedTables, int batchSize){ Statement javadb_stmnt = null; PreparedStatement mysql_stmnt = null;
try { for (int i = 0; i < orderedTables.length; i++){ //Print out some information on which table isbeing copied and how many rows that table contains. System.out.println("------ Copying table " + orderedTables[i] + " ------ "); int numberRows = DataBase.executeCountQuery(orderedTables[i], null); //A helper method for getting rows in table System.out.println(numberRows + " rows needs to be copied");
int totalNumberCopied = 0;//Get resultset from source table String selectQuery = "select * from " + orderedTables[i]; javadb_stmnt = javadb.createStatement(); ResultSet rs_select = javadb_stmnt.executeQuery(selectQuery); //Creating insert query for target table. Query will be 'insert into <tablename> values (?, ?, ..., ?)' int colCount = rs_select.getMetaData().getColumnCount(); String insert_query = "insert into " + orderedTables[i] + "( "; String valuesSubstring = "values ("; for (int j = 0; j < colCount-1; j++){ insert_query += rs_select.getMetaData().getColumnName(j+1) + ", "; valuesSubstring += "?, "; } insert_query += rs_select.getMetaData().getColumnName(colCount) + ") "; insert_query += valuesSubstring + "?)"; //Use prepared statement with batches mysql_stmnt = mysql.prepareStatement(insert_query); int counter = 0; //Iterate over resultset from source table while (rs_select.next()){ //Add batch to insert statement from the current row in result set for (int j = 1; j <= colCount; j++){ Object obj = rs_select.getObject(j); mysql_stmnt.setObject(j, obj); } mysql_stmnt.addBatch(); //If I have added enough inserts, execute the batch insert if (++counter == batchSize){ int[] arr = mysql_stmnt.executeBatch(); //Print out some progressinformation totalNumberCopied += arr.length; double progress = (1.0*totalNumberCopied) / (1.0*numberRows) * 100; DecimalFormat df = new DecimalFormat("#"); System.out.print("Executed batch for "+orderedTables[i]+", inserted " + arr.length + " elements"); System.out.println("\t Have copied a total of " + totalNumberCopied + "/" + numberRows + " rows, " + df.format(progress) + "%"); //Reset counter for batch size counter = 0; } } //Insert the last elements int[] arr = mysql_stmnt.executeBatch(); System.out.println("Executed batch for "+orderedTables[i]+", inserted the last " + arr.length + " elements"); System.out.println("------ Finished copying table " + orderedTables[i] + " ------ \n"); } } catch (SQLException ex) { Logger.getLogger(DataBaseCopier.class.getName()).log(Level.SEVERE, null, ex); } finally { try { javadb.close(); mysql.close(); } catch (SQLException ex) { Logger.getLogger(DataBaseCopier.class.getName()).log(Level.SEVERE, null, ex); } }
}