itsource

Java에서 Oracle로 대량 삽입

mycopycode 2023. 8. 15. 11:05
반응형

Java에서 Oracle로 대량 삽입

Oracle에 많은 작은 행을 빠르게 삽입해야 합니다. (5개 필드)

MySQL에서는 삽입물을 100개의 그룹으로 나눈 다음 100개의 삽입물 그룹마다 하나의 삽입문을 사용합니다.

그러나 Oracle의 경우 매스 삽입(1000-30000 범위)이 너무 느리다는 사용자 의견이 있습니다.

자바에서 오라클로 프로그램 삽입 속도를 높이기 위해 사용할 수 있는 유사한 트릭이 있습니까?

Spring의 DAO 모듈을 사용하여 많은 행을 일괄 삽입할 수 있습니다.

Order 개체 컬렉션을 한 번의 업데이트로 데이터베이스에 삽입하는 예:

public class OrderRepositoryImpl extends SimpleJdbcDaoSupport implements
        OrderRepository {

    private final String saveSql = "INSERT INTO orders(userid, username, coffee, coffeename, amount) "
            + "VALUES(?, ?, ?, ?, ?)";

    public void saveOrders(final Collection<Order> orders) {
        List<Object[]> ordersArgumentList = new ArrayList<Object[]>(orders
                .size());

        Object[] orderArguments;
        for (Order order : orders) {
            orderArguments = new Object[] { order.getUserId(),
                    order.getUserName(), order.getCoffe(),
                    order.getCoffeeName(), order.getAmount() };

            ordersArgumentList.add(orderArguments);
        }

        getSimpleJdbcTemplate().batchUpdate(saveSql, ordersArgumentList);
    }
}

이러한 레코드를 데이터베이스에 전달하는 방법에 대해 말하지 않습니다.가장 좋은 방법은 어레이를 사용하는 것입니다. 이렇게 하면 Oracle의 풍부한 FORNITY를 모든 대량 작업에 사용할 수 있습니다.

이 예제 패키지에는 두 가지 절차가 있습니다.하나는 T23 레코드 모음(5개의 숫자 열로 구성된 테이블)을 채우는 것이고 하나는 배열을 사용하여 해당 테이블에 레코드를 대량으로 삽입하는 것입니다.

SQL> create or replace package p23 as
  2      type t23_nt is table of t23%rowtype;
  3      function pop_array ( p_no in number )
  4          return t23_nt;
  5      procedure ins_table ( p_array in t23_nt );
  6  end p23;
  7  /

Package created.

SQL> create or replace package body p23 as
  2
  3      function pop_array ( p_no in number )
  4          return t23_nt
  5      is
  6          return_value t23_nt;
  7      begin
  8          select level,level,level,level,level
  9          bulk collect into return_value
 10          from dual
 11          connect by level <= p_no;
 12          return return_value;
 13      end pop_array;
 14
 15      procedure ins_table
 16              ( p_array in t23_nt )
 17      is
 18          s_time pls_integer;
 19      begin
 20
 21          s_time := dbms_utility.get_time;
 22
 23          forall r in p_array.first()..p_array.last()
 24              insert into t23
 25              values p_array(r);
 26
 27          dbms_output.put_line('loaded '
 28                  ||to_char(p_array.count())||' recs in '
 29                  ||to_char(dbms_utility.get_time - s_time)
 30                  ||' csecs');
 31      end ins_table;
 32  end p23;
 33  /

Package body created.

SQL>

다음은 일부 샘플 실행의 출력입니다.

SQL> declare
  2      l_array p23.t23_nt;
  3  begin
  4      l_array := p23.pop_array(500);
  5      p23.ins_table(l_array);
  6      l_array := p23.pop_array(1000);
  7      p23.ins_table(l_array);
  8      l_array := p23.pop_array(2500);
  9      p23.ins_table(l_array);
 10      l_array := p23.pop_array(5000);
 11      p23.ins_table(l_array);
 12      l_array := p23.pop_array(10000);
 13      p23.ins_table(l_array);
 14      l_array := p23.pop_array(100000);
 15      p23.ins_table(l_array);
 16  end;
 17  /
loaded 500 recs in 0 csecs
loaded 1000 recs in 0 csecs
loaded 2500 recs in 0 csecs
loaded 5000 recs in 1 csecs
loaded 10000 recs in 1 csecs
loaded 100000 recs in 15 csecs

PL/SQL procedure successfully completed.

SQL>
SQL> select count(*) from t23
  2  /

  COUNT(*)
----------
    119000

SQL>

0.15초 안에 100,000개의 레코드를 삽입하는 것은 가장 까다로운 사용자를 제외한 모든 사용자를 만족시켜야 한다고 생각합니다.문제는 삽입물에 어떻게 접근하느냐입니다.

현재 MySQL은 Oracle이므로 MySQL에 유지하는 것이 더 간단한 솔루션일 수 있습니다.

그렇지 않은 경우에는 삽입 그룹을 시작하기 전에 트랜잭션이 시작되었는지 확인해야 합니다. 그룹이 완료되면 트랜잭션을 커밋하고 다음 삽입 그룹에 대해 새 트랜잭션을 시작합니다.

또한 삽입 시간을 지연시킬 수 있는 불필요한 인덱스 정의도 확인합니다.

업데이트됨...
대량 삽입은 ETL(Extract Transform Load)의 마지막 단계를 의미하므로 펜타호 주전자나 탤런트 스튜디오와 같은 자바 기반 ETL 도구를 사용하는 것을 고려해 본 적이 있습니까?

Pentaho는 Oracle Bulk 로딩 기능을 여기에 설명합니다.

빠른 구글은 또한 Talend가 Oracle 대량 로딩을 지원한다는 예비 증거를 보여줍니다.

먹어봐.

public Boolean inserTable(String fileName) {
    logger.info("Begin - " + this.getClass().getSimpleName() + "." + "inserTable");
        logger.info("File : " + fileName);
    try (Connection conn1 =  jdbcTemplate.getDataSource().getConnection();) {
        OracleConnection conn = ( OracleConnection ) conn1.getMetaData().getConnection();
        ScriptRunner sr = new ScriptRunner(conn);
        StringBuilder sBuffer = new StringBuilder();
        StringBuffer sb=new StringBuffer();
        String query = "Insert into TABLE_DATA (ID, DATA1, DATECREATED, CREATEDBY) Values ";
        String line = "";
        //Creating a reader object
        BufferedReader br = new BufferedReader(new FileReader(fileName),1024 * 1024 );
        while ((line = br.readLine()) != null) {
            //logger.info("Leyo linea : " + line);
            sb.append(query.concat("(").concat("TABLE_DATA_SQ.NEXTVAL,").concat(line.substring(0,6)).concat(",").concat("sysdate,").concat("'BDVENLINEA'").concat(");"));
            sb.append("\n");
        }
        sb.append("commit;");
        Reader reader = new StringReader(sb.toString());
        //Running the script
        sr.runScript(reader);
        reader.close();
        br.close();
        return true;
    } catch (FileNotFoundException e) {
        logger.error(e.getMessage(), e);
        throw new TechnicalException(e, e.getMessage());
    } catch (SQLException e) {
        e.printStackTrace();
        throw new TechnicalException(e, e.getMessage());
    } catch (IOException e) {
        e.printStackTrace();
        throw new TechnicalException(e, e.getMessage());
    } finally {
        logger.info("End   - " + this.getClass().getSimpleName() + "." + "inserTable");
    }
}

언급URL : https://stackoverflow.com/questions/2716818/bulk-insert-from-java-into-oracle

반응형