문의가 와서 Oracle 10g에서 제공되기 시작한 model dimension by 에 대해 살펴보게 되었다.

DB2의 오라클 호환성이 어지간한 신택스는 다 지원된다고 생각하고 있었는데, 이런 엑셀스러운 신택스도 있는 것을 알게 된 것 같다.

 

처음보는 기능이기에 어떤 방식으로 처리되는지를 알고자 웹 검색을 해보니 “증분 누적?”(바로 전 값을 계속 누적 연산) 처리 로직정도로 이해가 되었다.

 

(참고) http://www.gurubee.net/lecture/2203

 

어떤 문서에는 common table (with 문을 통한 recursive 처리) 로의 변환이 되지 않게 쓰인 문서들도 있었는데 위의 참조된 웹 문서를 기준으로 db2 방식으로 변환을 해 보았다.

 

[예제1] 증분 누적

 

입력 값 및 결과

MM

AMT

결과 값

1

-2000

0

2

4000

4000

3

-5000

0

4

-2000

0

5

3000

3000

6

1500

4500

7

-250

4250

8

320

4570

9

-4000

570

10

10000

10570

11

-20000

0

 

변환 SQL

with

   t1(mm,amt) as

     (select * from

              (values(1,-2000),(2,4000),(3,-5000),(4,-2000),(5,3000),(6,1500),(7,-250),(8,320),(9,-4000),(10,10000),(11,-20000)) t(mm,amt)),


   tmp(c1,c2,c3) as
    (select mm, greatest(0,amt), amt from t1 where mm=1
        union all
     select c1+1,
            (select greatest(0,c2+amt) from t1 where mm=c1+1),
            (select amt from t1 where mm=c1+1)
     from tmp where c1 < (select max(mm) from t1)
    )


select c1,c3 amt, c2 result from tmp ;

 

[예제2] 행 분할 누적

 

입력값

M

AMT

1

100

5

200

6

100

9

300

 

결과

M

결과

1

100

2

100

3

100

4

100

5

200

6

100

7

100

8

100

9

300

10

300

11

300

12

300

 

변환 SQL

with
  t1(mm,amt) as

     (select * from (values(1,100),(5,200),(6,100),(9,300)) t(mm,amt)) ,


  tmp (c1,c2,c3) as
   (select t1.mm, t1.amt, t1.amt from t1 where t1.mm=1
    union all
    select c1+1,
           case when (select amt from t1 where c1+1 = mm) is null then c2
                else (select amt from t1 where c1+1 = mm) end ,
           (select amt from t1 where c1+1 = mm)
    from  tmp
    where c1 < 12 
    )


select c1, c2 from tmp
order by c1
;

 

SQL의 복잡성에 따라서 어떤 경우에는 위처럼 변환되지 않는 경우가 있을 수도 있겠다.

 

개인적으로 SQL 표현을 간소하게 하여 SQL 문을 단순화하고 직관적으로 볼 수 있는 것을 좋아하기에 SQL에 대해서는 Oracle SQL 철학을 좋아한다. (+, connect by 등)

표준 SQL을 준수하는 DB2에서는 이런 부분을 장문의 SQL로 표현을 해야 되는 번거로움을 느끼지만 common table의 미학을 느껴볼 수 있는 계기가 된 것 같다.

'Note' 카테고리의 다른 글

[관리] 메모리 부족  (0) 2014.11.21
[보안] authentication 과 srvcon_auth  (0) 2014.07.14
[보안] SSL 설정  (0) 2014.06.18
[관리] db2gcf  (0) 2014.05.19
[복구] 경로재지정 복구  (0) 2014.04.15

고객사 요청으로 기술지원을 갔다가 데이터 복구 작업을 해야 되는 경우가 있었다.

특정 테이블의 데이터 복구 작업 시 업무 영향도를 최소화하기 위해서 개발 시스템에 운영DB의 백업 이미지를 경로재지정 복구를 수행하여 필요한 데이터를 추출하는 방법으로 작업을 진행하였다.

 

문제는 개발서버의 자원이 운영시스템만큼 풍족하지 못하고, 이미 개발DB가 존재하기 때문에 복구 중 rollforward 작업이 진행되지 못하게 되었다.

rollforward를 수행하면서 내부적으로 DB가 활성화되는 것 같은데, 개발서버의 물리적 메모리의 가용량이 DB가 필요로 하는 메모리 크기가 되지 못해서 생긴 것 같다.  마치 대저택에서 살던 사람이 사업이 망해 단칸방으로 세간살이를 옮겨야 되는 경우와 비슷한..

 

인스턴스 메모리 및 DB 메모리를 변경해도 이 문제는 해결되지 않았다. STMM이 수행되어도 DB내 설정된 버퍼풀의 크기를 충족하지 못해 DB가 활성화되지 못하는..

 

해결 방안을 얻고자 자료들을 찾아보니, Registry 변수에서 버퍼풀 크기를 강제로 제어하는 변수를 알게 되었다.

DB2_OVERRIDE_BPF=버퍼풀ID,페이지수;버퍼풀ID,페이지수

 

운영DB를 통해서 가장 큰 (페이지수가 많은) 버퍼풀ID와 페이지 수를 확인을 하고 크기를 줄여나갔다.

 

이 변수를 적용하고 나서 rollforward 작업 진행되어 데이터 복구 작업을 완료할 수 있었다.

 

이후 언젠가 블로그 글을 살펴보면서 같이 일했던 동료분이 “실수로 bufferpool 크기를 과도하게 설정한 경우 해결하는 방법”으로 글이 적혀둔걸 보게 되었다. (남의 경험이 공유되어도 직접 비슷한 경험을 하지 않는 이상 급박한 상황에서 해결안을 쉽게 찾아내긴 어려운 법 같다.)

고객사 시스템에 직접 터미널로 붙어서 작업하는 환경이 없어져서 장애관련 정보를 수집하고 메모하는 것이 어려워진다. 그저 기억속으로만 간직해야 되는

 

'Note' 카테고리의 다른 글

[SQL] model dimension by  (0) 2015.01.08
[보안] authentication 과 srvcon_auth  (0) 2014.07.14
[보안] SSL 설정  (0) 2014.06.18
[관리] db2gcf  (0) 2014.05.19
[복구] 경로재지정 복구  (0) 2014.04.15

DBM 구성변수에서 지원하는 보안 관련 변수에는 authentication과 srvcon_auth 가 있다.

정보센터를 통해서 보면 동일한 기능을 하는 것처럼 보이는데, 변수를 2개나 제공을 하고 있다.

 

내용을 면밀히 읽어보면, authentication 설정 값보다 srvcon_auth 값이 우선한다고 하는 정도의 차이점이 있겠다.

 

1. server 쪽 DBM CFG 설정

$ db2 update dbm cfg using authentication data_encrypt
$ db2 update dbm cfg using srvcon_auth server

$ db2 get dbm cfg | grep AUTH
Server Connection Authentication          (SRVCON_AUTH) = SERVER
Database manager authentication        (AUTHENTICATION) = DATA_ENCRYPT

 

 

2. client 쪽 catalog 설정

$ db2 catalog db sample at node inst97 authentication data_encrypt

 

3. 접속 결과

$ db2 connect to sample user inst97 using inst97

SQL30082N  이유 "17"("UNSUPPORTED FUNCTION")(으)로 인해 보안 처리에 실패했습니다.  SQLSTATE=08001

 

4. client쪽 catalog 설정

$ db2 catalog db sample at node inst97 authentication server

 

5. 접속 결과

$ db2 connect to sample user inst97 using inst97

  Database Connection Information

Database server        = DB2/AIX64 9.7.2
SQL authorization ID   = INST97
Local database alias   = SAMPLE

 

두 변수의 설정 값이 다른 경우 srvcon_auth 설정값으로 접속이 됨을 확인할 수 있다.

srvcon_auth 값이 설정되지 않는 경우 authentication 값이 적용이 된다.

 

보안관련하여 위 변수들의 값을 data_encrypt 등으로 변경하는 경우 client side에서도 관련하여 설정 작업이 필요하다.

WAS의 경우는 다음과 같은 TechNote를 참고하면 도움이 될 듯 하다.

 

Configure DB2 authorization encryption algorithm

http://www-01.ibm.com/support/docview.wss?uid=swg21503216

'Note' 카테고리의 다른 글

[SQL] model dimension by  (0) 2015.01.08
[관리] 메모리 부족  (0) 2014.11.21
[보안] SSL 설정  (0) 2014.06.18
[관리] db2gcf  (0) 2014.05.19
[복구] 경로재지정 복구  (0) 2014.04.15

V9.5 까지는 OS 환경변수 설정하여 SSL을 구성하였으나, V9.7부터 DBM 구성변수로 SSL 설정 변수들이 포함되었다.

최근에 보안 사고로 인해 각종 보안 조치사항들이 취해지다 보니 DB 쪽의 SSL 구성 요건도 생기는 듯 하다.

 

오래된 버전에서는 SSL 관련 라이브러리를 별도 설치를 했었어야 되는 것 같은데, V9.7부터 DB2 설치 시 SSL 관련 라이브러리(IBM GSKit)들이 설치된다.

 

1. 설치 경로

    - DB2_엔진경로/gskit

    - 인스턴스_홈/sqllib/gskit

 

2. DB2 서버 쪽의 설정

   인스턴스 경로를 /db2user/inst97로 가정한다.

   (1) 환경변수 설정 (.profile)

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/db2user/inst97/sqllib/gskit/bin
export PATH=$PATH:/db2user/inst97/sqllib/gskit/bin

 

   (2) 인스턴스 홈에 SSL 디렉토리 생성

$> mkdir ~/SSL

 

  (3) 키 생성

$> cd ~/SSL
$>

gsk8capicmd_64 -keydb -create -db "key.kdb" -pw "password" –stash

 

  (4) 인증서 추가

$> gsk8capicmd_64 -cert -create -db "key.kdb" -pw "password" -label "DBCNI" -dn "CN=ssl.dbcni.com,O=dbcni,OU=dbcni db2,L=GANGNAM,ST=SEOUL,C=KR"

     - CN= common name

     - O = organization

     - OU= orgnaization unit

     - L = location

     - ST=state,province

     - C = country

     - DC= domain component

 

  (5) 인증서 추출

$> gsk8capicmd_64 -cert -extract -db "key.kdb" -pw "password" -label "DBCNI" -target "key.arm" -format ascii -fips

 

  (6) 유효성 검증

$> ls

      key.arm, key.crl, key.kdb, key.rdb, key.sth

 

   (7) DBM CFG 설정

db2 update dbm cfg using SSL_SVR_KEYDB /db2user/inst97/SSL/key.kdb
db2 update dbm cfg using SSL_SVR_STASH /db2user/inst97/SSL/key.sth
db2 update dbm cfg using SSL_SVR_STASH /db2user/inst97/SSL/key.sth
db2 update dbm cfg using SSL_SVR_LABEL DBCNI
db2 update dbm cfg using SSL_SVCENAME 50602

 

   (8) Registry 설정

db2set db2comm=ssl,tcpip

 

2. 클라이언트 설정

    (1) SSL 디렉토리 생성 (AIX 기준)

$> mkdir ~/SSL

     (주의) DB2 서버에서 생성된 key.arm 파일을 SSL 디렉토리 하위에 넣어 둘것

 

   (2)  key 디비 생성

$> cd ~/SSL
$> gsk8capicmd_64 -keydb -create -db "keyclient.kdb" -pw "password" -stash

 

   (3) 인증서 서명

$> gsk8capicmd_64 -cert -add -db "keyclient.kdb" -pw "password" -label "DBCNI" -file key.arm -format ascii -fips

 

   (4) dbm cfg 설정

db2 update dbm cfg using SSL_CLNT_KEYDB /db2/instance/db2inst/SSL/keyclient.kdb
db2 update dbm cfg using SSL_CLNT_STASH /db2/instance/db2inst/SSL/keyclient.sth


   (5) 카탈로스 설정

$> db2 catalog tcpip node 노드별명 remote IP server 50602 security ssl
$> db2 catalog db 디비명 as 디비SSL at node 노드별명
$> db2terminate

   (참고) TCPIP 통신 설정을 위해서는 카탈로그 작업이 한번 더 진행되어야 한다. 

 

   (6) 접속 테스트

$> db2 connect to 디비SSL user ID using PWD

 

DB2COMM 설정에 TCPIP도 있기 때문에 DB2 서버의 SVCENAME의 설정값을 통하여 TCPIP 방식의

DB 접속도 가능하다. (TCPIP 용 , SSL용 2가지 방식으로 통신이 됨)

 

참고로 V10.5의 경우 FixPack3a가 올라왔다. SSL관련하여 bug 발생으로 긴급 패치가 이뤄졌다.

이외 V10.1, V9.x 버전도 마찬가지로 보안관련 패치가 된 것으로 보인다.

SSL 설정 작업 시 각 버전의 APAR 등을 참고해야 될 것 같다.

'Note' 카테고리의 다른 글

[관리] 메모리 부족  (0) 2014.11.21
[보안] authentication 과 srvcon_auth  (0) 2014.07.14
[관리] db2gcf  (0) 2014.05.19
[복구] 경로재지정 복구  (0) 2014.04.15
[관리] Backup Pending 풀기  (0) 2014.03.31

db2gcf 명령어는 이중화하는 경우에 주로 사용된다.

V9.5부터 TSA (Tivoli System Automation) 클러스터가 도입이 된 후 이중화 관련 tsa의 script를 보면 db2 제어를 위해 db2gcf가 사용됨을 확인할 수 있다.

 

인스턴스 시작(u), 중지(d), 상태(s) 를 확인할 수 있고, 강제로 자원을 정리하는 k 옵션도 제공한다.

Unix 환경이나 Linux 환경에서 DB2 인스턴스가 패닉 상태에 놓인 경우 db2stop 명령어로 인스턴스가 중지되지 않아, db2_kill 이라는 명령어를 사용한다. 그러나 윈도우 환경에서는 db2_kill 이라는 명령어는 제공되지 않는다.

 

윈도우 작업관리자에서 정리를 할 수 밖에 없기 때문에 db2_kill 같은 명령어의 필요성이 느껴질 수 있다.

이때 db2gcf –k 를 사용하면 db2_kill과 같은 효과를 얻을 수 있으니 다급한 상황이 발생한 경우는 db2gcf 를 사용하는 것이 도움이 될 듯 하다.

 

주의 사항은 DB 활성화 시  crash recovery가 진행되므로, 만약의 경우를 대비하여 복구에 필요한 백업 이미지, 아카이브 로그 등을 확인 후 작업해야 할 것이다.

 

참고: http://www-01.ibm.com/support/knowledgecenter/?lang=ko#!/SSEPGG_10.5.0/com.ibm.db2.luw.admin.cmd.doc/doc/r0010986.html?cp=SSEPGG_10.5.0%2F3-5-2-6-56

'Note' 카테고리의 다른 글

[보안] authentication 과 srvcon_auth  (0) 2014.07.14
[보안] SSL 설정  (0) 2014.06.18
[복구] 경로재지정 복구  (0) 2014.04.15
[관리] Backup Pending 풀기  (0) 2014.03.31
[구성] Federation MS-SQL Server  (0) 2014.03.20

데이터가 삭제되었거나, 동일한 H/W환경에 백업 이미지로 테스트 DB 환경을 만들어야 되는 경우 db의 경로를 다르게 하여 restore를 해야 할 필요가 생긴다. 이럴 경우 테이블 공간 혹은 스토리지 그룹의 경로를 일일이 적어주는 것은 불편할 것이다.

 

경로재지정 복구 작업을 위해 db2는 해당 필요한 script를 만들어 준다. (V9.1 부터 지원된다)

 

-- script 추출

db2 “restore db 디비명 from 백업_경로 taken at 백업_시간소 redirect generate script 경로재지정_복구.clp

-- 추출 script 예
RESTORE DATABASE SAMPLE
-- USER '<username>'
-- USING '<password>'
FROM '/home/jseifert/backups' TAKEN AT 20050906194027
-- DBPATH ON '<target-directory>'
INTO SAMPLE
-- NEWLOGPATH '/home/jseifert/jseifert/NODE0000/SQL00001/SQLOGDIR/'
-- WITH <num-buff> BUFFERS
-- BUFFER <buffer-size>
-- REPLACE HISTORY FILE
-- REPLACE EXISTING REDIRECT
-- PARALLELISM <n>
-- WITHOUT ROLLING FORWARD
-- WITHOUT PROMPTING

SET TABLESPACE CONTAINERS FOR 0
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS USING ( PATH 'SQLT0000.0' );

SET TABLESPACE CONTAINERS FOR 1
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS USING ( PATH 'SQLT0001.0' );

SET TABLESPACE CONTAINERS FOR 2
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS USING ( FILE '/tmp/dms1' 1000 , FILE '/tmp/dms2' 1000 );

RESTORE DATABASE SAMPLE CONTINUE;

 

DB이름, DB 경로, 테이블공간 경로 등 여러 경로를 원하는 방식으로 변경하여 복구 작업을 진행하면 된다.

 

과거 V8에서는 해당 script를 일일이 만들다 보면 신택스 오류가 발생하여 script 만드는 데 시간이 많이 소요되었다.

(운영체제에 따라 시스템 테이블 공간은 지정해주지 않아도 알아서 경로재지정이 복구가 진행되기도 했었다.)

 

많이 쓰이는 기능은 아니나, 지워진 데이터를 찾아내기 위해서 혹은 공간 부족으로 다른 곳으로 경로를 변경해야 되는 경우가 있을 때

 

이 방법을 쓰면 작업 진행에 도움이 될 것 같다.

'Note' 카테고리의 다른 글

[보안] SSL 설정  (0) 2014.06.18
[관리] db2gcf  (0) 2014.05.19
[관리] Backup Pending 풀기  (0) 2014.03.31
[구성] Federation MS-SQL Server  (0) 2014.03.20
[성능] Actual Section & db2caem  (0) 2014.02.28

DB2는 기본적으로 순환로그(circular logging) 방식으로 DB 생성이 된다. 따라서 사용된 트랜잭션 로그를 보관(Archive logging)하기 위해서는 LogArchMeth1 이라는 DB 구성변수에 “트랜잭션 로그를 보관할 장소"를 설정해 주어야 한다.

그리고 변경 후에는 Offline DB 백업을 수행해야 DB가 정상 상태에 놓인다.

 

DB 구성 초기에 Archive logging 모드로 변경하는 것은 어려운 일이 아니나, 백업 정책 및 기타 운영 관련 정책이 한참 운영 중인 상태에

서 변경을 하게 되는 경우 난감한 일이 발생한다.

DB의 데이터 사이즈가 작다면 큰 문제가 없지만 백업 수행이 오래 걸릴 정도의 사이즈가 되는 경우 백업으로 인해 장시간 운영을 중단해야 되는 상태가 놓이기 때문이다.

이 부분은 DB2의 단점이 될 수 있는 부분인데, DB2 관련 정보를 찾다가 백업하지 않아도 백업 보류 상태(backup pending)를 풀 수 있는 방법을 알게 되었다.

 

db2dart에서 지원해 주는 기능이고, 오래된 옛 버전부터 지원된 기능인데 왜 이 기능이 존재감없이 묻혀져 있었는지 의문이 든다.

(너무 당연한 것 이여서 그랬을까?)

 

Archive logging 모드 상태에서 대용량 데이터를 load로 적재한 후 발생하는 Backup Pending,

초기 데이터 적재 작업 시, 아카이브 로그의 대량 발생을 막기 위해 circular logging 을 사용하고 적재 완료 후 archive logging 으로 전환하고자 하는 경우,

 

db2dart를 통해서 짧은 시간안에 backup pending을 풀 수 있다.

 

$> db2 update db cfg for sample using logarchmeth1 logretain
DB20000I  UPDATE DATABASE CONFIGURATION 명령이 완료되었습니다.

$> db2 connect to sample
SQL1116N  데이터베이스가 BACKUP PENDING 단계에 있기 때문에 데이터베이스 "SAMPLE"에 연결하거나 활성화하는데 실패했습니다.

 

$> db2dart sample /CHST /WHAT DBBP OFF


                              IMPORTANT:
  After resetting the database backup pending state, IBM no longer
  guarantees data integrity or the referential integrity of the data.
  To ensure the referential integrity of the data, all user tables
  should be exported, the database dropped and recreated and all
  user tables imported back into the new database.


Updated the log file header control file.
        The requested DB2DART processing has completed successfully!
                 Complete DB2DART report found in: SAMPLE.RPT

$> db2 connect to sample

  데이터베이스 연결 정보

데이터베이스 서버                        = DB2/NT64 10.5.0
SQL 권한 부여 ID                         = BRAD
로컬 데이터베이스 별명                   = SAMPLE

$> db2 backup db sample online compress

백업이 완료되었습니다.

'Note' 카테고리의 다른 글

[관리] db2gcf  (0) 2014.05.19
[복구] 경로재지정 복구  (0) 2014.04.15
[구성] Federation MS-SQL Server  (0) 2014.03.20
[성능] Actual Section & db2caem  (0) 2014.02.28
[성능] SQL Optimizer Profile  (0) 2014.02.06

보통은 이관 작업을 위한 Oracle Federation 구성 정도가 전부인데, 일이 생겨서 MS-SQL Server의 Federation 구성을 하게 되었다.

MS-SQL 서버 Federation을 위해서는 InfoSphere Federation Server를 설치하던가, DB2 서버 설치 후 DB2 FixPack 사이트에서 관계형 wrapper와 비관계형 wrapper 설치 파일을 내려받아 설치를 해야 한다. (Advanced E/W Server Edition로는 구성 불가능)

 

또한 MS-SQL 서버에 원격 접속을 할 수 있도록 환경 구성을 위해 ODBC 클라이언트가 필요하다.

 

1. ODBC Driver 내려받기

    - 경로: ftp://ftp.software.ibm.com/software/db2ii/downloads/odbc_driver/

    - 드라이버 버전 정보: DataDirect ODBC Version 7.1

 

2. 설치 (root 계정)

    - 설치위치: /db2/v10.1f/odbc_driver  (기본 경로: /opt/IBM/ODBC_Driver)

#> export LANG=C
#> ./install.bin

 

3. 환경 설정 (인스턴스 계정)

    (1)  환경 변수 설정

$> cat ~/sqllib/userprofile << EOF

export ODBCINI=/instance/inst10f/odbc.ini
export DJX_ODBC_LIBRARY_PATH=/db2/v10.1f/odbc_driver/branded_odbc/lib
#export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$DJX_ODBC_LIBRARY_PATH
export LIBPATH=\$LIBPATH:\$DJX_ODBC_LIBRARY_PATH

EOF

(주의) LIBPATH는 AIX 환경 변수 임 (운영체제에 맞는 변수명 사용 필요)

 

     (2) db2dj.ini 설정

$> cat ~/sqllib/cfg/db2dj.ini << EOF

DJX_ODBC_LIBRARY_PATH=/db2/v10.1f/odbc_driver/branded_odbc/lib
ODBCINI=/instance/inst10f/odbc.ini

EOF

 

   (3) ODBC 설정

        - 설정 파일 위치: 설치경로/branded_odbc/IBM_Tools/odbc.ini

        - MSSQL서버 정보: 192.168.137.109:1433

                           계정: sa/sa1111

                           DB  : test

                           DSN: testdsn

 

[ODBC Data Sources]
mssqlserver=Microsoft SQL Server

[ODBC]
IANAAppCodePage=4
InstallDir=/db2/v10.1f/odbc_driver
Trace=0
TraceDll=/db2/v10.1f/odbc_driver/branded_odbc/lib/VMtrc00.so
TraceFile=odbctrace.out
UseCursorLib=0


[testdsn]
Driver=/db2/v10.1f/odbc_driver/branded_odbc/lib/VMsqls00.so
Description=DataDirect 7.1 SQL Server Wire Protocol
Database=test
HostName=192.168.137.109
PortNumber=1433
LogonID=sa
password=sa1111

 

        - 연결테스트

$> cd /db2/v10.1f/odbc_driver/branded_odbc/samples/example
$> ./example testdsn

Enter the user name        : sa

Enter the password         : sa1111

SQL> select * from t1;
6066:
[IBM(DataDirect OEM)][ODBC 20101 driver]2711
[IBM(DataDirect OEM)][ODBC 20101 driver]6091

C1    C2
1     aaa
2     mssql2012
3     sqlserver


SQL> select * from sys.tables;

 

 

4. Federation 서버 구성

(1) 라이브러리 확인

$> ls –al DB2_설치경로/lib64/libdb2mssql*

-r-xr-xr-x 1 bin bin  76184 2013-11-17 16:33 libdb2mssql3.so
-r-xr-xr-x 1 bin bin 506698 2013-11-17 16:33 libdb2mssql3F.so
-r-xr-xr-x 1 bin bin 356907 2013-11-17 16:33 libdb2mssql3U.so

 

(2) 서버 구성

   - 랩퍼명: sql2000

   - 서버명: sql2012

   - 노드명: testdsn   (odbc dsn 명)

   - DB명  : test

   - 사용자 매핑: inst10f(db2) 사용자를 sa(mssql) 로 매핑함

$> db2set DB2LIBPATH=$LIBPATH

$> db2set DB2ENVLIST=DB2LIBPATH

$> db2stop force

$> db2start

$> db2 connect to sample
$> db2 "create wrapper sql2000 library 'libdb2mssql3.so'"

$> db2 "create server sql2012 TYPE mssqlserver VERSION '2012' Wrapper sql2000 options(add node 'testdsn', dbname 'test')"

$> db2 "create user mapping for inst10f server sql2012 options (add remote_authid 'sa',add remote_password 'sa1111')"

$> db2 "set passthru sql2012"

$> db2 "select * from t1"

C1          C2
----------- --------------------
          1 aaa
          2 mssql2012
          3 sqlserver

  3 record(s) selected.


$> db2 "set passthru reset"

'Note' 카테고리의 다른 글

[복구] 경로재지정 복구  (0) 2014.04.15
[관리] Backup Pending 풀기  (0) 2014.03.31
[성능] Actual Section & db2caem  (0) 2014.02.28
[성능] SQL Optimizer Profile  (0) 2014.02.06
[이관] lobsinfile 및 tempfiles path  (0) 2014.01.27

두 개념 모두 V9.7에서 나온 것으로 알고 있다.

옵티마이저가 SQL을 어떻게 계획을 수립하여 실행할 지를 알고자  access plan을 보지만, 이것은 예상 계획일 뿐 “실제로 실행한 plan”을 보여주지는 않는다.

실제 수행한 plan에 대한 정보는 db2에서 actual section 이라는 개념으로 제공되고 actual section을 얻기 위해서는 “워크로드"와 “이벤트 모니터"를 사용해야 된다.

 

1. actual section을 수집하기 위한 절차

   (1) DB CFG 구성변수 설정 - section_actuals (값: base)

   (2) Workload 생성           - 수집하고자 하는 SQL을 수행하는 application name 을 알아야 함

   (3) Event Monitor 생성

   (4) Explain 시간소 확인    -  저장 프로시저 EXPLAIN_FROM_ACTIVITY 수행

   (5) db2exfmt 수행하여 plan 정보 수집

 

2. 테스트

   - db2 서버 local에서 테스트를 하기 때문에 application name 이 db2bp.exe 에 대하여 workload를 생성함

# APP NAME 이름 확인
$> db2 list applications  

# db2bp.exe에 대한 워크로드 wl1 생성
$> db2 "create workload wl1 applname('db2bp.exe') collect activity data with details, section"      

# 사용 권한 PUBLIC 으로 설정
$> db2 "grant usage on workload wl1 to public"

# 이벤트 모니터 생성
$> db2 "create event monitor actevmon for activities write to table"

# 활성화
$> db2 "set event monitor actevmon state 1"

# SQL 수행 (db2bp.exe가 수행되는 터미널/CLP 창에서 수행)

# APP ID, UOW ID 등 확인
$> db2 "select varchar(appl_id,20) appl_id, uow_id, activity_id, varchar(stmt_text,50) stmt_text from activitystmt_actevmon"

APPL_ID                    UOW_ID         ACTIVITY_ID          STMT_TEXT
*LOCAL.DB2_01.140129           2                    1      select * from employee whe



# Explain 시간 확인
$> db2 "call explain_from_activity('*LOCAL.DB2_01.140129001143',2,1,'ACTEVMON','BRAD',?,?,?,?,?)"

출력 매개변수 값
--------------------------
매개변수 이름: EXPLAIN_SCHEMA
매개변수 값: BRAD

매개변수 이름: EXPLAIN_REQUESTER
매개변수 값: BRAD

매개변수 이름: EXPLAIN_TIME
매개변수 값: 2014-01-29-09.25.36.178000

매개변수 이름: SOURCE_NAME
매개변수 값: SQLC2K26

매개변수 이름: SOURCE_SCHEMA
매개변수 값: NULLID

매개변수 이름: SOURCE_VERSION
매개변수 값:

리턴 상태 = 0



# Actual Section 수집
$> db2exfmt -d sample -w 2014-01-29-09.25.36.178000 -n SQLC2K26 -s NULLID -# 0 -t

Access Plan:
-----------
        Total Cost:             6.8165
        Query Degree:           1

             Rows
          Rows Actual
            RETURN
            (   1)
             Cost
              I/O
              |
              10
             10
            FETCH
            (   2)
            6.8165
              NA
         /----+----\
       10            42
       10            NA
     IXSCAN    TABLE: BRAD
     (   3)       EMPLOYEE
   0.00851615        Q1
       NA
       |
       42
       NA
INDEX: BRAD
   PK_EMPLOYEE
       Q1


# 이벤트 모니터 비활성화
$> db2 "set event monitor actevmon state 0"

 

위 plan의 경우 예측된 rows 값과 actual rows값이 동일하다. 즉 통계정보 갱신이 적절히 되어 차이가 존재하지 않음을 알 수 있다.

actual section 의 존재에 대해서는 알게 된지 오래 되었지만, 설정 작업이 많고 application name 등을 확인해야 하는 등 불편함이 느껴져서 잘 쓰게 되지 않았다.

 

db2 문서들을 검색하다 알게된 db2caem 이라는 유틸리티를 통해서도 actual section을 수집할 수 있다.

위와 같은 여러 수행 절차없이 원하는 SQL 구문만 알고 있으면 actual section 정보를 수집할 수 있다.

(주) caem: Capture Activity Event Monitor data tool

 

3. db2caem 테스트

$> db2pd -db sample -dbcfg | grep -i section

SECTION_ACTUALS                NONE                 NONE

$> cat > 02.sql1.db2 <<EOF
select * from t2 where c2 > 0 ;
EOF

$> db2caem -d sample -sf 02.sql1.db2 –o 출력경로

$> cat 출력경로/db2caem.exfmt.1

Access Plan:
-----------
        Total Cost:             7.58138
        Query Degree:           1

      Rows
   Rows Actual
     RETURN
     (   1)
      Cost
       I/O
       |
        7
       8
     TBSCAN
     (   2)
     7.58138
       NA
       |
        8
       NA
TABLE: DB2INST
       T2
       Q1

 

actual section 을 통해서 옵티마이저가 계획한 방식대로 수행되었는지 확인을 할 수 있고,

건수의 차이를 통하여 통계정보의 적절성을 판단할 수 있을 것 같다.

요즘에도 오라클의 Hint가 SQL 튜닝의 방법으로 선호되는지 모르겠다.

JAVA 기반의 개발 환경에서 iBatis 등을 이용하여 XML 파일에 SQL을 중앙집중화(?) 방식으로 사용하는 추세이고, 오라클 아닌 다른 DBMS를 사용하더라도 개발된 SQL 수정없이 사용하는 요건이 중요해 지면서 “특정 DBMS의 기능”에 편중되는 방식은 지양되고 있는 것 같다.

사용 중인 오라클이 버전 업그레이드를 한다던가 하는 경우에 Hint가 사용된 SQL은 성능 저하를 일으키는 경우을 들어 본 적도 있다.

 

SQL의 성능 개선으로 Hint 사용이 중요한 튜닝 방법으로 인식되어 왔지만, 개인적으로 이런 방법은 “호환되지 않는" 구속성이 있어 튜닝 방법으로서는 부정적인 시각으로 보게 되었다.

 

DB2에서 실행 계획 변경은 Optimizer Guideline 이라는 XML 방식으로 한다.

간편한 방식은 SQL 뒤에 XML 태그를 붙이는 방식으로 많이 알려진 방식이다. 이외 optimizer profile 을 만들어서, 즉 ibatis의 xml 처럼 XML 문서에 SQL과 Guideline을 설정하여 사용도 가능하다.

 

1. 테스트 시나리오

   - 목적: 데이터 정렬을 ORDER BY 를 사용하지 않고, Index를 이용하여 오름차순으로 데이터 결과 집합을 반환

   - 테이블 명: T2  (컬럼: C1, C2, C3)

   - 인덱스    : T2_IDX2 (C2)

                    T2_IDX3 (C2, C3)

db2 +p -tv << EOF
connect to sample ;
drop table t2 ;
create table t2 (c1 int, c2 int, c3 int) ;
create index t2_idx2 on t2 (c2) ;
create index t2_idx3 on t2 (c2,c3) ;

insert into t2 values (1,5,10),(2,10,9),(3,3,8),(4,6,7),(5,9,6),(6,7,5),(7,5,1),(8,3,4);
runstats on table inst15.t2 and detailed indexes all ;

terminate ;
EOF

 

     - 테스트 SQL

db2 "select * from t2 where c2 > 0"

 

2. OPTIMIZER PROFILE 기능 적용

db2set db2_optprofile=yes
db2start

 

3. 실행 계획 확인

-- PLAN 테이블 생성
$ db2 "call sysproc.sysinstallobjects('EXPLAIN','C',NULL,CURRENT SCHEMA)"

-- 최적화 프로파일 테이블 생성
$ db2 "call sysproc.sysinstallobjects('OPT_PROFILES', 'c', '', CURRENT SCHEMA)"

cat > opt1.db2 << EOF
select * from t2 where c2 > 0
EOF


$ db2expln -d sample -f opt1.db2 -g –t
….

Optimizer Plan:

 Operator
   (ID)

RETURN
  ( 1)
   |
 TBSCAN
  ( 2)
   |
Table:
INST15
T2

 

-- 결과 값

C1          C2          C3
----------- ----------- -----------
          1           5          10
          2          10           9
          3           3           8
          4           6           7
          5           9           6
          6           7           5
          7           5           1
          8           3           4

* table scan이 선택된 이유는, 데이터가 적기 때문에 Index Scan 이 비효율적이라고 Optimizer 가 판단을 했기 때문이다.

  ( 통계정보를 갱신하지 않고 plan을 확인했다면 index scan이 수행되었을 것이다. 초보 시절 index scan 하던 것이 통계 수집 후 table scan 한 것을 이상하게 생각한 적이 있었다 ^^; )

 

4. 프로파일 작성 및 등록

파일명: opt1.xml

<?xml version="1.0" encoding="UTF-16"?>
 
<OPTPROFILE VERSION="10.5.0">

<STMTPROFILE ID="TEST1">
    <STMTKEY>
             <![CDATA[select * from t2 where c2 > 0]]>
    </STMTKEY>
 
    <OPTGUIDELINES>
            <IXSCAN TABLE="T2" INDEX="T2_IDX2"/>
    </OPTGUIDELINES>
</STMTPROFILE>
</OPTPROFILE>

(참고) XML 문서 명은 “스키마명.프로파일명.업무명.xml” 식으로 사용하는 것이 관리 상 좋을 것 같다.   “업무명"은 해당 SQL을 쉽게 파악할 수 있는 “업무 단위” 혹은 “테이블 단위” 등으로 명명하면 될 것 같다.

 

등록

cat > opt1.del << EOF
"INST15","TEST","opt1.xml"
EOF

 

$ db2 import from opt1.del of del modified by lobsinfile replace into systools.opt_profile

(주의) 스키마 명(INST15), 프로파일명(TEST)”를 지정해야 한다.

        프로파일명은 임의적이고, 스키마 명은 PLAN 테이블의 스키마 명을 지정한다.

 

5. PLAN 변경 확인

-- 프로파일 명 지정

$ db2 SET CURRENT OPTIMIZATION PROFILE="TEST"

 

-- PLAN만 수집

$ db2 SET CURRENT EXPLAIN MODE EXPLAIN

 

-- SQL 수행

$ db2 "select * from t2 where c2 > 0"

 

-- PLAN 확인

$ db2exfmt -d SAMPLE -1 -o exfmt1.out

$ cat exfmt1.out

Profile Information:
--------------------

OPT_PROF: (Optimization Profile Name)
        INST15.TEST
STMTPROF: (Statement Profile Name)
    
   TEST1


Access Plan:
-----------
        Total Cost:             6.83711
        Query Degree:           1

                Rows
               RETURN
               (   1)
                Cost
                 I/O
                 |
                  7
               FETCH
               (   2)
               6.83711
                  1
           /-----+-----\
          7               8

...skipping one line
       (   3)            T2
      0.0233252          Q1
          0
         |
          8
 INDEX:    INST15
       T2_IDX2
         Q1

 

$ db2 SET CURRENT EXPLAIN MODE no

$ db2 "select * from t2 where c2 > 0"

 

C1          C2          C3
----------- ----------- -----------
          3           3           8
          8           3           4
          1           5          10
          7           5           1
          4           6           7
          6           7           5
          5           9           6
          2          10           9

  8 record(s) selected with 1 warning messages printed.

 

만일 C2와 C3에 대해서 오름차순 정렬을 한다면

db2 +p –tv << EOF
connect to sample ;
select * from t2 where c2 > 0
/* <OPTGUIDELINES>
     <IXSCAN TABLE='T2' INDEX='T2_IDX3'/>
   </OPTGUIDELINES>
*/ ;
EOF

-- 결과

C1          C2          C3
----------- ----------- -----------
          8           3           4
          3           3           8
          7           5           1
          1           5          10
          4           6           7
          6           7           5
          5           9           6
          2          10           9

 

Embedded SQL 및 Package 에서 Guideline을 적용하려는 경우,  prepare 단계에서 profile을 선언하면 된다.

 

문서 참고: http://pic.dhe.ibm.com/infocenter/db2luw/v10r5/index.jsp?topic=%2Fcom.ibm.db2.luw.admin.perf.doc%2Fdoc%2Fc0024522.html

 

테스트는 Windows, Linux, AIX에서 했으나, Windows에서는 Guideline 이 수행되지 않았다.

table scan이 발생하는 SQL을 Index Scan으로 우회할 수 있다면, Guideline을 사용하는 것이 도움을 줄 수 있을 것이다.

성능이 좋지 않은 SQL을 디자인 어드바이저(db2advis) 등을 통하여 개선되지 않는 경우, 고려를 해 보면 좋을 듯 하다.

+ Recent posts