java构建大型文件的动态查询
我试图加载一个大的文本文件(介于400-800MB之间),并且对于要将记录插入数据库的文件,但是我遇到了性能问题和内存问题(没有足够的堆空间)。我想知道从我目前的工作中是否有更好的方法
因此,我正在加载的文本文件具有简单的格式,它类似于:
00000 Andy 8920 N UNL ...
00001 Roger 4428 N TRX ...
,,,
当前方法:读取每一行,获取字段,然后构建查询
ArrayList<ArrayList<String>> fields = ArrayList<ArrayList<String>>();
ArrayList<String> data= new ArrayList<String>();
while ((line = br.readLine()) != null) {
if(line.length() >= 6)
data.add(line.substring(0, 6));
if(line.length() >= 24)
data.add(line.substring(6, 15));
if(line.length() >= 30)
data.add(line.substring(15, 20));
if(line.length() >= 48)
data.add(line.substring(20, 25));
...
fields.add(data); //it looks like [[00000, Andy , 8920,..],[00001, Roger, ...]]
} //end read
System.gc();
db.insertValues(input);
DB代码
public void insertValues(ArrayList<ArrayList<String>> data) {
PreparedStatement ps = null;
Connection con = null;
try {
con = getConnection();
ps = con.prepareStatement("Insert into CUST_ACCT "
+ "(CID,NAME,R_NUM,CKM_IND,DATE_1,DATE_2,DATE_3,DATE_4,DATE_5,DATE_6,DATE_7,DATE_8,DATE_9,DATE_10,NUMBER_1,NUMBER_2,NUMBER_3,NUMBER_4,NUMBER_5,NUMBER_6,NUMBER_7,NUMBER_8,NUMBER_9,NUMBER_10,STRING_1,STRING_2,STRING_3,STRING_4,STRING_5,STRING_6,STRING_7,STRING_8,STRING_9,STRING_10,GUID,PARN_GUID,LAST_UPDT_DATE_TIME_STAMP)"
+ " values "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,sysdate)");
for(int i=0; i< data.size(); i++) {
ps.setString(1, data.get(i).get(0)); //0
ps.setString(2, data.get(i).get(1)); //1
ps.setString(3, data.get(i).get(2)); //2
ps.setString(4, data.get(i).get(3)); //3
...
ps.addBatch();
}
int[] i = ps.executeBatch();
log.info("total of record inserted: "+i.length);
}
然而,我得到了Not enough heap space
错误,我也尝试构建查询,但它会一个接一个地插入记录,一个小时后它只会插入数百万条记录中的大约20k条。是否有更好的方法加载数据
# 1 楼答案
将所有文件加载到内存中,然后尝试逐行读取所有文件,这会导致性能和内存问题(堆空间等)
您可以使用
Scanner
读取文件,这样就可以逐行读取,而无需加载到内存中否则使用Apache Commons IO
为了更好的表现,我建议你只打开一次连接
总结起来:
希望你能理解。。。这些都是简单的例子,你需要根据自己的需要来选择它们
# 2 楼答案
让我看看我是否正确理解您的需求:
您有一个大文件,文件中的每一行都需要插入数据库中的更多表。我理解对了吗
如果是,您是否尝试过使用Oracle的"SQL*Loader"工具? 我没有测试这么大的文件,但它可能是一个解决方案。 你可以通过Java应用程序调用它
# 3 楼答案
不要读取整个文件——读取1000行,然后使用准备好的语句插入它们,然后提交事务。然后再读1000
此外,我认为Oracle有一个加载数据的特殊工具(google SQL*Loader和data pump)