我有一数据文件要写入到derby数据库中,数据文件列数不一致。
我采用读一行,处理一行,插入数据库的方式。
但太慢,5W行的数据,要处理20分钟。
由于数据文件列数不一致,所以我表中记录了行号,列号,及值,
所以是不能用导入内部过程的。
请教有没有一种方法在1分钟内搞定从数据文件到数据库的写入?

解决方案 »

  1.   

    http://www.3800hk.com/Article/cxsj/java/cjkjava/2005-08-06/Article_22415.html
      

  2.   

    源代码如下,请大家指教:
    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
    每个数据文件列数不一样。
      

  3.   

    Operator.sleep(RF_SleepTime);
    是什么?
      

  4.   

    这个每操作一行让它睡眠18ms,这个可以去掉的。现在主要是hibernate做 session.save的时候是瓶颈。
    我去把它换了,用批量插入试试看。
      

  5.   


    经验之谈:这种事情不要用HIBERNATE,直接用JDBC算了,快得多。HIBERNATE暗地里做了好多无用功
      

  6.   

    也是,你的业务需求很明确,还不如直接用JDBC方便的多,更直接
      

  7.   

    可以用jdbc直接组成一个大sql
    如果要用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();
      

  8.   

    谢谢大家,我一个数据文件的内容,先进行行处理,然后数据主要存储在两个表中,
    如果不用hibernate批量插入,需要8分钟,用hibernate批量插入batch_size设为50,
    可以缩短到4分钟。
    直接JDBC批量插入我没试。
    我采取的策略是直接用derby的内部系统过程SYSCS_UTIL.SYSCS_IMPORT_DATA,
    先把我的数据文件,按表的格式处理成2个相应的数据文件,然后导入derby。
    这样5.6W行的原数据文件,导入需要1分钟以内。