我有一数据文件要写入到derby数据库中,数据文件列数不一致。
我采用读一行,处理一行,插入数据库的方式。
但太慢,5W行的数据,要处理20分钟。
由于数据文件列数不一致,所以我表中记录了行号,列号,及值,
所以是不能用导入内部过程的。
请教有没有一种方法在1分钟内搞定从数据文件到数据库的写入?
我采用读一行,处理一行,插入数据库的方式。
但太慢,5W行的数据,要处理20分钟。
由于数据文件列数不一致,所以我表中记录了行号,列号,及值,
所以是不能用导入内部过程的。
请教有没有一种方法在1分钟内搞定从数据文件到数据库的写入?
public static void loadSpeciesData(Species species, File file)
throws Throwable {
// var
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
// Species
line = br.readLine();
line = line.trim();
species.setUrl(line);
DBMetaData.saveSpecies(species);
// create session
Session session = mainData.getSession();
// SpeciesCol
String[] colType = br.readLine().trim().split("\t");
String[] colName = br.readLine().trim().split("\t");
SpeciesCol[] speciesCols = new SpeciesCol[colType.length];
for (int col = 0; col < speciesCols.length; col++) {
speciesCols[col] = new SpeciesCol();
speciesCols[col].setIdSpecies(species.getId());
speciesCols[col].setCol((long) col);
speciesCols[col].setName(colName[col]);
speciesCols[col].setDt(mainData.getDTi(colType[col]));
session.save(speciesCols[col]);
}
// SpeciesRow
long row = 0;
while ((line = br.readLine()) != null) {
long start2 = System.currentTimeMillis();
line += " "; // java正则分离,防止最后没有数据而少项
String[] rowdata = line.split("\t");
// SpeciesRow
SpeciesRow speciesRow = new SpeciesRow();
speciesRow.setIdSpecies(species.getId());
speciesRow.setRow(row++);
speciesRow.setGenename(rowdata[0].trim());
speciesRow.setChr(rowdata[1].trim());
speciesRow.setPositionStart(Long.parseLong(rowdata[2].trim()));
speciesRow.setPositionEnd(Long.parseLong(rowdata[3].trim()));
session.save(speciesRow);
// SpeciesValue
for (int col = 4; col < speciesCols.length; col++) {
long start5 = System.currentTimeMillis();
SpeciesValue speciesValue = new SpeciesValue();
speciesValue.setIdSpecies(species.getId());
speciesValue.setRow(speciesRow.getRow());
speciesValue.setCol(speciesCols[col].getCol());
speciesValue.setDt(speciesCols[col].getDt());
switch (speciesCols[col].getDt()) {
case DT_char:
case DT_epistasis:
case DT_moption:
case DT_option:
speciesValue.setValueChar(rowdata[col].trim());
break;
case DT_num:
speciesValue.setValueNum(Long
.parseLong(rowdata[col].trim()));
break;
}
session.save(speciesValue);
}
Operator.sleep(RF_SleepTime);
}
br.close();
session.close();
}
数据文件
http://www.tigr.org/tigr-scripts/osa1_web/gbrowse/rice/?name=
Char option num num char option moption epistasis
Genename chrnum start end Gene description W/C pfam ID protein interaction
LOC_Os01g01010 1 1 7364 RabGAP/TBC domain-containing protein, putative, expressed + PF00566
LOC_Os01g01020 1 8174 9019 cytochrome P450 family protein, putative - LOC_Os01g01010
LOC_Os01g01030 1 9523 12619 Monocopper oxidase precursor, putative, expressed + PF00394|PF07732|PF07731 LOC_Os01g01010
LOC_Os01g01040 1 13123 16979 expressed protein + LOC_Os01g01010
LOC_Os01g01050 1 19643 23696 R3H domain containing protein, expressed + PF01424 LOC_Os01g01010
LOC_Os01g01060 1 23940 25437 40S ribosomal protein S5, putative, expressed + PF00177 LOC_Os01g01010
每个数据文件列数不一样。
是什么?
我去把它换了,用批量插入试试看。
经验之谈:这种事情不要用HIBERNATE,直接用JDBC算了,快得多。HIBERNATE暗地里做了好多无用功
如果要用hibernate的话,不能这么循环,否则很容易出现内存溢出!因为每次save的时候都会把该记录添加到一级缓存里,很影响性能。
建议像hibernate文档中说的那样每隔一段时间就进行一下flush和clear,例如:
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size //20,与JDBC批量设置相同
//flush a batch of inserts and release memory:
//将本批插入的对象立即写入数据库并释放内存
session.flush();
session.clear();
}
}
tx.commit();
session.close();
如果不用hibernate批量插入,需要8分钟,用hibernate批量插入batch_size设为50,
可以缩短到4分钟。
直接JDBC批量插入我没试。
我采取的策略是直接用derby的内部系统过程SYSCS_UTIL.SYSCS_IMPORT_DATA,
先把我的数据文件,按表的格式处理成2个相应的数据文件,然后导入derby。
这样5.6W行的原数据文件,导入需要1分钟以内。