Q&A

  • 동적배열을 Table 로 insert 하는 방법질문
다음과 같이 TRec 타입을 선언하고
type
  TRec = record
    a  : String ;  
    b  : Double;  
    c  : Double;  
End;

==== 중간생략  ====

var
  Dyn_Rec : Array of TRec //TRec 동적배열를 잡아 주었습니다.

==== 중간생략  ====

setlength(Dyn_Rec ,10)

  Dyn_Rec[0].a := 'A'
  Dyn_Rec[0].b := 1000
  Dyn_Rec[0].c := 2000
  Dyn_Rec[1].a := 'A'
  Dyn_Rec[1].b := 3000
  Dyn_Rec[1].c := 4000
        .
        .
        .
        .
  Dyn_Rec[9].a := 'A'
  Dyn_Rec[9].b := 9900
  Dyn_Rec[9].c := 8800
  
여기서 질문
이 배열은 흔히 말하는 2차원 배열의 형태를 티고 있습니다.
레코드를 다시 배열로 잡았으니까  테이블의 형태와도 유사하고요

C 언어 에서는  이럴때

  INSERT INTO T_TEST ( a, b, c)
  VALUES ( :Dyn_Rec ) ;

이렇게 하면  위 쿼리 한방에 배열 전체의 내용을
입력할 수 있습니다. 위 쿼리 한문장으로 열건의 데이터가 입력됩니다.

델파이에서는 쿼리 컴포넌트를 쓰고 있는데
다음과 같이 루프를 이용해서 돌리면 배열의 수만큼 DB transaction 이
발생해서 db 에 불필요한 오버헤드가 발생합니다.
만약 배열이 엄청나게 크다면 문제는 심각해 지겠구요

  for i := 0 to length(Dyn_Rec) -1 do
  begin
    SQL.ADD(' INSERT INTO  AAA (A , B, C) ');
    SQL.ADD(' VALUES (:A, :B, :C);

      ParamByName('A').AsString := Dyn_Rec[i].a
      ParamByName('B').AsString := Dyn_Rec[i].b
      ParamByName('C').AsString := Dyn_Rec[i].c
    
  end;  
        
위의 방법 말구 루프를 돌지 않으면서 동적배열의 내용을 한방에 INSERT 하는
방법이 있을것 같은데  여기 저기 찾아봐도 잘 나오지 않습니다.
방법을 아시는 분은 답글좀 꼭 달아주세요

2  COMMENTS
  • Profile
    열심히 2003.11.22 13:58
    잘은 모르겠지만..

    님꼐서 적어주신 C언어의 문법은 보기엔 한방에 들어가는것처럼 보이지만.

    DB입장에서 보면 insert문의 쿼리가

    insert into table_name
    (select .... from ... where ...)

    이런 식이 아니면 여러줄의 레코드를 한번에 집어넣을수 없을겁니다.

    그리고 루핑을 돌린다고 해도 님꼐서는 transaction을 스타트 하지 않으셨기때문에 transaction자체가 생기지 않았구요..

    (제가 잘몰라서 프로그램에서 transaction을 걸지 않으면 자동으로
    transaction start - querying - commit or rollback
    이렇게 될지도 모르겠군요..)

    transaction이 문제라면 시작하기전에 start해주고 작업이 끝난후 commit 해주시면 한트랜잭션안에서 작업을 하겠지요..그리 해주는게 맞을거 같네요..

    오라클 9i에는 여러건의 레코드를 넣는 쿼리가 있기는 한데 이건 쓸수 없을것 같구요..

    프로시져로 작성해도 되구요. 이것도 내부적으로는 루핑을 돌리는거지만..

    가장 쉽고 좋은 방법은 트랜잭션 걸고 루핑돌리는거네요..

    제생각엔 C에서도 그렇게 내부적으로 처리 됐을거 같아요..

    트랜잭션을 거십시오..몇천건 정도는 가뿐할겁니다.(성능에 따라 틀리겠지만)


  • Profile
    박경진 2003.11.24 23:02
    우선 성섬껏 답변해주셔셔 감사하구요 님의 말씀에 제 소견을 조금만 적을까 합니다.

    트랜젝션을 하나로 하여 처리한다는 점에서는 동감합니다.
    또 그렇게 하구 있구요. 10만건 insert 시 10만건 모두 insert 한후 commit을
    하죠... 당연한 얘기일 거구요...

    제가 궂이 Array를 이용하여 한방에 작업할려고 하는 이유는 루핑을 돌리기 싫어서는 아닙니다.

    for 문을 이용하여 10만건의 데이터를 10만번 insert 문을 날리면 2시간 이상의
    시간이 걸립니다.
    그런데 Array Processing 을 이용하여 한방에 처리하면 약 3분 미만의 시간이 걸립니다. 실로 엄청난 차이가 난다는 것이죠...

    대용량의 데이터를 단시간에 처리하기 위합이죠....

    님께서는 Array 를 이용하여 한방에 처리하더라도 내부적으로 또 루프를 돌면서 처리한다고 하셨습니다만....

    루핑을 이용하여 insert 문을 10만번 날리면 DB는 10만건의 데이터를 insert 하기 위해 10만번 sql을 실행합니다.
    (물론 static sql 을 이용하면 sql parsing 은 한번 Dynamic sql을 사용하면 parsing 도 10만번 수행하는 최악의 상황이 되겠죠)
    어쨋든 for 를 이용한 방법은 별로 권장할 만한 방업은 아니라는 생각이 듭니다.

    반면에 Array 를 이용하면 데이터가 많더라도 하나의 배열안에 있으면 sql 실행 단 한번에 insert 처리할 수 있습니다. 어프리케이션 부하도 적도 DB 에 무리도 덜 가고....