【发布时间】:2017-10-30 14:26:43
【问题描述】:
我正在尝试加载一个大文本文件(介于 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);
数据库代码
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 错误的 _e_rror 并且我也尝试构建查询,但是它会一个接一个地插入记录,一个小时后它只会插入大约 20k 个记录百万。有没有更好的方法来加载数据?
【问题讨论】:
-
你不应该把整个内容放在内存中,按块读取文件(例如100行),然后在每个读取块之后使用批量插入。
-
我很确定您的 DBMS 中有针对此类文件的自动导入功能。
-
正如@Berger 所说,创建合理的批处理(每 100 或 1000 行,执行批处理并开始下一个)。然后,中型 Oracle 服务器应该能够每秒导入 100 ... 1000 行这样的行。
-
虽然我同意文件大小是问题的一部分,但我认为问题也是 arraylist 中的 arraylist 的一部分,当我使用整个文件大小构建动态查询时,如果我增加堆大小,但是添加arraylist的arraylist会立即导致它出堆。
标签: java sql oracle performance