在我的Java应用程序中,我需要在硬盘上存储一个大表,因为我希望它是持久的。
我的第一次尝试是这样的: (i& j可以爬到300.000甚至更多,所以我有一个300.000 ^ 2的双重数据,这会导致我的系统崩溃。)
stmt.executeUpdate("DROP TABLE IF EXISTS calculations;");
stmt.executeUpdate("CREATE TABLE calculations (factorA, factorB, result);");
double temp = 0;
for (i = 0; i < datasource.size(); i++) {
for (int j = 0; j < datasource.size(); j++) {
if (i != j) {
temp = calc(datasource.get(i),datasource.get(j));
stmt.execute("INSERT INTO calculations (factorA, factorB, result) VALUES ('"+i+"','"+j+"','"+temp+"')");
}
}
}
现在,这执行速度极慢,可能是因为SQL命令是一个字符串等。
我的新猜测是,首先计算结果,即10.000 i,然后将它们作为一个单元存储到数据库中可能会更好。
但在我尝试实施之前,是否有人有更好的想法?数据库使用不是强制性的,只需轻松访问并快速实施。
答案 0 :(得分:1)
尝试在n
内添加每个Transaction
左右的行(假设失败不是问题,例如,如果某些行无法插入,则可以继续而不回滚之前的行)。
在循环中声明一个反ous:
int n = 1000; //commit every 1000 rows, or you can tweak
int count = 0; //counter for rows inserted
在外部循环中启动事务。增加并检查内循环中的计数器
if(count % n == 0){
//commit the transaction
}
count++
(别忘了在外循环中再次重新打开Transaction)
http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html
答案 1 :(得分:1)
int BLOCK_SIZE = 15000;
stmt.executeUpdate("DROP TABLE IF EXISTS calculations;");
stmt.executeUpdate("CREATE TABLE calculations (factor_idx text NOT NULL PRIMARY KEY,result text NOT NULL);");
double temp = 0;
int block_ctr = 1;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < datasource.size; i++) {
for (int j = 0; j < datasource.size; j++) {
if (i != j) {
temp = calc(a, b);
// init the statement when counter = 1
if (block_ctr == 1) {
sb.append("INSERT INTO 'calculations' SELECT '" + i + "_" + j + "' AS 'factor_idx', '" + temp + "' AS 'result'");
}
// then commit only every BLOCK_SIZE blocks
if (block_ctr <= BLOCK_SIZE) {
sb.append("UNION SELECT '" + i + "_" + j + "','" + temp + "'");
} else {
stmt.execute(sb.toString());
sb.setLength(0); // better then creating a new sb
block_ctr = 0;
}
block_ctr++;
}
}
}
我减少了列数,并使用StringBuilder创建了一个组合语句。它应该快得多,允许使用您创建连接i和j的主键列上的索引更快地读取。试着让我知道,我很好奇:)