엠바카데로에서 FireDAC Skill Sprint 웨비나(1월 23일 ~ 3월 27일: 매주 금요일 10시)를 진행하고 있습니다.


이 글에서는 웨비나 다시보기와 함께 웨비나 일부 내용을 샘플코드와 함께 소개합니다. 하단 온라인 기술 도움말 링크를 통해 더 자세한 내용을 추가학습하시기 바랍니다.


4회차에는 Array DML에 대한 내용으로 진행합니다.

Array DML 이란?

Array DML은 실행에 필요한 매개변수(Parameters) 배열을 이용한 한번에 DBMS 명령을 실행하는 기능입니다. 이 방법은 DBMS와 애플리케이션 사이의 통신비용을 줄이고 DBMS 명령 요청을 줄입니다. 그 결과 실행 속도가 향상됩니다.


다음 그림에서 이 프로세스를 보여줍니다.


동영상을 보셨다면 아시겠지만 1만건의 데이터를 DBMS에 입력 시

  • 트랜젝션으로 작업을 묶어주면 20배 빨라지고, 

  • Array DML을 사용하면 다시 10배가 더 빨라진다고 설명합니다.

Array DML의 사용법 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
with FDQuery1 do begin
  SQL.Text := 'insert into Customers (ID, RegionID, Name, Note) values (:ID, :RegionID, :Name, :Note)';
  // Set up parameter types
  Params[0].DataType := ftInteger;
  Params[1].DataType := ftInteger;
  Params[2].DataType := ftString;
  Params[2].Size := 40;
  Params[3].DataSize := ftMemo;
  // Set up parameters' array size
  Params.ArraySize := 10000;
  // Set parameter values
  for i := 0 to 10000 - 1 do begin
    if i mod 100 = 0 then
      // force PK violation
      Params[0].AsIntegers[i] := i - 1
    else
      Params[0].AsIntegers[i] := i;
    Params[1].AsIntegers[i] := GetRegionIdForCustomer(i);
    Params[2].AsStrings[i] := 'Somebody ' + IntToStr(i);
    Params[3].Clear(i);
  end;
  // Execute batch
  Execute(10000, 0);
end;

  • 위 코드 10번째 줄에서 배열크기(Params.ArraySize)를 지정합니다.
  • 13~20번 줄에서는 Params[0].AsStrings[i] 형태로 배열로 데이터를 입력합니다.(AsString 뒤에 s가 붙은 것을 유의하세요.)
  • 데이터 입력 후 23번째 줄에 Execute 메소드로 실행요청을 합니다. 이때 배열의 크기를 인자로 넘겨줍니다.

Array DML 샘플 프로그램 소개

이 샘플에서는 만건의 데이터를 3가지 방식으로 입력하고 실행 시간을 출력합니다. 

  • 아무 튜닝없이 반복하며 입력 - 13,244 ms 소요
  • 트랜젝션으로 작업을 묶어서 입력 - 1,062 ms 소요
  • Array DML으로 데이터 일괄 입력 - 160 ms 소요
결과를 보면 Array DML의 결과가 매우 빠르다는 것을 볼수 있습니다. 
또한 단순하게 트랜젝션 처리만 추가해도 10배 이상 속도가 개선된 결과도 인상적입니다.

[샘플코드 받기 - 데브기어 github 페이지]


Insert STD - 아무 튜닝없이 반복하며 입력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var
  I: Integer;
  StopWatch: TStopwatch;
begin
  FDConnection1.ExecSQL('DELETE FROM Test');
 
  StopWatch := TStopWatch.StartNew;
 
  for I := 0 to NUM_INSERTS - 1 do
  begin
    FDQuery1.ParamByName('Field1').AsInteger := I;
    FDQUery1.ParamByName('Field2').AsString := 'Str' + I.ToString;
    FDQuery1.ExecSQL;
  end;
 
  StopWatch.Stop;
  Memo1.Lines.Add('Insert STD : ' + StopWatch.ElapsedMilliseconds.ToString + ' ms');

Insert STD(Transaction) - 위 작업에 트랜젝션만 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var
  I: Integer;
  StopWatch: TStopwatch;
begin
  FDConnection1.ExecSQL('DELETE FROM Test');
 
  StopWatch := TStopWatch.StartNew;
 
  // Transaction 추가
  FDConnection1.StartTransaction;
  try
    for I := 0 to NUM_INSERTS - 1 do
    begin
      FDQuery1.ParamByName('Field1').AsInteger := I;
      FDQUery1.ParamByName('Field2').AsString := 'Str' + I.ToString;
      FDQuery1.ExecSQL;
    end;
  finally
    FDConnection1.Commit;
  end;
 
  StopWatch.Stop;
  Memo1.Lines.Add('Insert STD(Transaction) : ' + StopWatch.ElapsedMilliseconds.ToString + ' ms');

Insert Array DML - Array DML을 이용해 입력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var
  I: Integer;
  StopWatch: TStopwatch;
begin
  FDConnection1.ExecSQL('DELETE FROM Test');
 
  StopWatch := TStopWatch.StartNew;
 
  FDConnection1.StartTransaction;
  try
    FDQuery1.Params.ArraySize := NUM_INSERTS;
    for I := 0 to NUM_INSERTS - 1 do
    begin
      FDQuery1.ParamByName('Field1').AsIntegers[I] := I;
      FDQUery1.ParamByName('Field2').AsStrings[I] := 'Str' + I.ToString;
    end;
    FDQuery1.Execute(NUM_INSERTS);
  finally
    FDConnection1.Commit;
  end;
 
  StopWatch.Stop;
  Memo1.Lines.Add('Insert ArrayDML : ' + StopWatch.ElapsedMilliseconds.ToString + ' ms');
번호 제목 글쓴이 날짜 조회 수
공지 [DelphiCon 요약] 코드사이트 로깅 실전 활용 기법 (Real-world CodeSite Logging Techniques) 관리자 2021.01.19 15443
공지 [UX Summit 요약] 오른쪽 클릭은 옳다 (Right Click is Right) 관리자 2020.11.16 13962
공지 [10.4 시드니] What's NEW! 신기능 자세히 보기 관리자 2020.05.27 16499
공지 RAD스튜디오(델파이,C++빌더) - 고객 사례 목록 관리자 2018.10.23 22055
공지 [데브기어 컨설팅] 모바일 앱 & 업그레이드 마이그레이션 [1] 관리자 2017.02.06 23268
공지 [전체 목록] 이 달의 기술자료 & 기술레터 관리자 2017.02.06 18923
공지 RAD스튜디오(델파이, C++빌더) - 시작하기 [1] 관리자 2015.06.30 39259
공지 RAD스튜디오(델파이,C++빌더) - 모바일 앱 개발 사례 (2020년 11월 업데이트 됨) 험프리 2014.01.16 174726
983 Release Notes for XE5 Update 1 c2design 2013.10.29 3380
982 [마이그레이션] 64비트 적용 시 검토할 사항들 file 험프리 2017.02.08 3375
981 CodeRage 8: Delphi 온라인 무료 세미나 개최 관리자 2013.10.15 3362
980 VCL앱을 모바일앱으로 쉽게 확장할 수 있는 앱테더링 자세히 살펴보기! [3] Humphery 2014.11.11 3359
979 SVN 서버 설치하기 - Visual SVN 이용 험프리 2016.02.29 3348
978 [추가된 문법 정리] - 배열 상수 초기화:델파이 XE7 추가 관리자 2016.06.03 3325
977 XE5용 업데이트2 가 공개되었습니다. 관리자 2013.12.16 3315
976 XE7에서 추가 된 안드로이드 프로젝트에서 외부 라이브러리(jar) 사용을 위한 정보 [1] Humphery 2014.11.03 3224
975 이 달의 강의 - 2015년 11월 관리자 2015.01.22 3192
974 안드로이드에서 NFC 연동 방법 Humphery 2014.09.12 3138
973 이전버전에서 최신버전으로 마이그레이션(업그레이드) 참고문서 Humphery 2014.02.28 3116
972 [베를린] TBufferedFileStream을 이용해 TFileStream 보다 더 빠르게 파일을 읽고, 쓸수 있습니다. file 험프리 2016.05.09 3085
971 [추가자료] 안드로이드 개발환경 추가 조치방법 - 수동 SDK Tools 업데이트 file Humphery 2015.10.01 3058
970 QR/바코드 스캐너 앱 샘플코드(ZXing, TFrameStand 사용) [1] 험프리 2017.08.04 3048
969 [따라하기] FireDAC으로 오라클(Oracle) DB와 연결하기 험프리 2015.03.24 3044
968 FireDAC 시작하기 Humphery 2014.09.23 2960
967 Developer Direct LIVE! 모바일 썸머 스쿨!! 관리자 2013.07.06 2954
966 안드로이드 SDK 설정 방법 file 험프리 2016.09.20 2869
965 파이어몽키(FireMonkey) vs. VCL 관리자 2017.07.18 2843
964 [도서/PDF/소스코드] 시작하는 사람들을 위한 델파이 프로그래밍-모듈 21. 2차원 배열들 관리자 2019.03.29 2840