db2에는 아직 ALTER TABLE tblName DROP PARTITION partName 구문이 없기 때문에

1. 파티션을 detach

2. 파티션테이블로부터 detach 된 single table을 drop

의 단계로 진행해야 한다.


이 때, detach 동작은 background에서 asynchronous하게 동작하므로

실제로 detach가 되어 single table로 떨어져나간 시점에 DROP TABLE을 수행하여야 하는데

partition detach가 금방 수행완료될 지 아닐 지는 알 수가 없다.


이러한 고려사항을 포함하여 간편하게 수행할 수 있는 프로시저의 소스는 아래와 같다.


-- db2 -td@ -vf dropPartition.sql

-- in dropPartition.sql

CREATE OR REPLACE PROCEDURE DBA.DROP_PARTITION (IN tblSchema VARCHAR(40), IN tblName VARCHAR(60), IN partName VARCHAR(120))

SPECIFIC DROP_PARTITION

LANGUAGE SQL

BEGIN

DECLARE tblSchema VARCHAR(40) DEFAULT '___________';

DECLARE detachSQL VARCHAR(2000);

DECLARE dropSQL VARCHAR(2000);

DECLARE isTblAbsent INT;


        DECLARE dpID INT;

        DECLARE dpState CHAR;

        DECLARE isNormalState INT DEFAULT 0;


        DECLARE curDPLock CURSOR FOR

                SELECT DATAPARTITIONID, STATUS

                FROM SYSIBM.SYSDATAPARTITIONS DP

                WHERE DP.TABSCHEMA = tblSchema

                AND DP.TABNAME = tblName

                AND (STATUS = 'L' OR STATUS = 'D' OR STATUS = 'I');


        DECLARE CONTINUE HANDLER FOR NOT FOUND

                SET isNormalState = 1;



CALL DBA.chkTblExist (tblSchema, tblName, isTblAbsent);

        IF isTblAbsent = 1

        THEN

                RETURN -1;

        END IF;


SET detachSQL = 'ALTER TABLE '  || tblSchema || '.' || tblName || ' DETACH PARTITION '|| partName || ' INTO ' || tblSchema || '.' || tblName || '_' || partName || '_DETACHED';

--CALL DBMS_OUTPUT.PUT_LINE(detachSQL);

EXECUTE IMMEDIATE detachSQL;

EXECUTE IMMEDIATE 'COMMIT WORK';


        WAIT_LOOP:

        LOOP

                OPEN curDPLock;

                FETCH curDPLock INTO dpID, dpState;

                CLOSE curDPLock;


                IF isNormalState = 1

                THEN

                        LEAVE WAIT_LOOP;

                ELSE

                        ITERATE WAIT_LOOP;

                END IF;

        END LOOP;


SET dropSQL = 'DROP TABLE ' || tblSchema || '.' || tblName || '_' || partName || '_DETACHED';

-- CALL DBMS_OUTPUT.PUT_LINE(dropSQL);

EXECUTE IMMEDIATE dropSQL;

EXECUTE IMMEDIATE 'COMMIT WORK';


RETURN 0;

END@


--

/* Sample Table DDL

DROP TABLE INODE.TMP;

CREATE TABLE INODE.TMP  (

OPRN_DT VARCHAR(8) NOT NULL ,

RIDE_TROP_ID VARCHAR(9) NOT NULL ,

RIDE_STN_NO VARCHAR(4) NOT NULL ,

ALGH_TROP_ID VARCHAR(9) NOT NULL ,

ALGH_STN_NO VARCHAR(4) NOT NULL ,

MTAR_AREA_CD VARCHAR(2) NOT NULL ,

RIDE_NCNT INTEGER NOT NULL WITH DEFAULT 0 ,

ALGH_NCNT INTEGER NOT NULL WITH DEFAULT 0 ,

RIDE_TTPS_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

ALGH_TTPS_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

RIDE_AMT BIGINT NOT NULL WITH DEFAULT 0 ,

ALGH_AMT BIGINT NOT NULL WITH DEFAULT 0 ,

RIDE_VLT_AMT BIGINT NOT NULL WITH DEFAULT 0 ,

DC_AMT BIGINT WITH DEFAULT 0 ,

GNPS_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

TNPS_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

CHPS_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

SNCN_PSNG_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

DSPR_PSNG_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

NTMP_NUM BIGINT NOT NULL WITH DEFAULT 0 ,

FRGN_SNCN_PSNG_NUM BIGINT WITH DEFAULT 0 ,

FRAP_PSNG_NUM BIGINT WITH DEFAULT 0 ,

DW_LST_UPD_DTM VARCHAR(14) NOT NULL )

COMPRESS YES ADAPTIVE

DISTRIBUTE BY HASH(RIDE_STN_NO)

INDEX IN TR_MT16_I01 PARTITION BY RANGE(OPRN_DT)

(PART TMP_P201600 STARTING(MINVALUE) ENDING('20151299') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201601 STARTING('20160101') ENDING('20160199') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201602 STARTING('20160201') ENDING('20160299') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201603 STARTING('20160301') ENDING('20160399') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201604 STARTING('20160401') ENDING('20160499') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201605 STARTING('20160501') ENDING('20160599') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201606 STARTING('20160601') ENDING('20160699') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201607 STARTING('20160701') ENDING('20160799') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201608 STARTING('20160801') ENDING('20160899') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201609 STARTING('20160901') ENDING('20160999') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201610 STARTING('20161001') ENDING('20161099') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201611 STARTING('20161101') ENDING('20161199') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201612 STARTING('20161201') ENDING('20161299') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201701 STARTING('20170101') ENDING('20170199') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201702 STARTING('20170201') ENDING('20170299') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201703 STARTING('20170301') ENDING('20170399') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201704 STARTING('20170401') ENDING('20170499') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201705 STARTING('20170501') ENDING('20170599') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201706 STARTING('20170601') ENDING('20170699') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201707 STARTING('20170701') ENDING('20170799') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201708 STARTING('20170801') ENDING('20170899') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201709 STARTING('20170901') ENDING('20170999') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201710 STARTING('20171001') ENDING('20171099') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201711 STARTING('20171101') ENDING('20171199') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201712 STARTING('20171201') ENDING('20171299') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201801 STARTING('20180101') ENDING('20180199') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201802 STARTING('20180201') ENDING('20180299') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201803 STARTING('20180301') ENDING('20180399') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201804 STARTING('20180401') ENDING('20180499') IN TR_MT16_D01 INDEX IN TR_MT16_I01,

PART TMP_P201805 STARTING('20180501') ENDING('20180599') IN TR_MT16_D01 INDEX IN TR_MT16_I01);

CREATE UNIQUE INDEX INODE.PK_TMP ON KSCCDW.TMP (OPRN_DT ASC, RIDE_TROP_ID ASC, RIDE_STN_NO ASC, ALGH_TROP_ID ASC, ALGH_STN_NO ASC, MTAR_AREA_CD ASC) PARTITIONED;

ALTER TABLE INODE.TMP ADD CONSTRAINT PK_TMP PRIMARY KEY (OPRN_DT,RIDE_TROP_ID,RIDE_STN_NO,ALGH_TROP_ID,ALGH_STN_NO,MTAR_AREA_CD);

*/


-- Sample detach partition SQL

-- db2 "CALL DBA.DROP_PARTITION('INODE','TMP','TMP_P201601')"


Posted by in0de
,

간단하게도 /usr/local/bin/db2ls 를 실행하면 확인할 수 있다.

 

 

db2ls -q -p -b ${installed_path} 를 수행하면 에디션 정보도 확인 가능하다.

 

 

Posted by in0de
,

원문 : http://use-the-index-luke.com/sql/explain-plan/db2/getting-an-execution-plan


DB2의 실행계획을 처음 접하는 사람들은 아스키 아트 형태의 실행계획을 잘 읽지 못한다.

사실 이렇게 보기 좋게 실행계획을 아스키 아트로 만들어준 DB2 개발자들의 노력에 감사하지만
쿼리가 조금만 길어져도 한 화면에 실행계획 트리가 다 나오지 않아, 그 노력이 무색하다.


DB2에서는 db2expln, db2exfmt, SYSTOOLS.EXPLAIN* 세 종류 방식으로 실행계획을 조회해볼 수 있는데
이 중 SYSTOOLS.EXPLAIN*을 사용하여, 비교적 오라클 스타일의 실행계획을 보여주는 View가 있어서 소개한다.


1. 다음 프로시저를 실행하여 EXPLAIN 정보를 담을 SYSTOOLS.EXPLAIN_STREAM 테이블을 생성한다.


db2 "CALL SYSPROC.SYSINSTALLOBJECTS('EXPLAIN', 'C', CAST (NULL AS VARCHAR(128)), CAST (NULL AS VARCHAR(128)))"


2. 다음 프로시저를 생성한다.


db2 -tvm +p <<EOF
-- Copyright (c) 2014-2017, Markus Winand - NO WARRANTY
-- Modifications by Ember Crooks - NO WARRANTY
-- Info & license: http://use-the-index-luke.com/s/last_explained
--
--#SET TERMINATOR ;

CREATE OR REPLACE VIEW last_explained AS
WITH tree(operator_ID, level, path, explain_time, cycle)
AS
(
SELECT 1 operator_id
     , 0 level
     , CAST('001' AS VARCHAR(1000)) path
     , max(explain_time) explain_time
     , 0
  FROM SYSTOOLS.EXPLAIN_OPERATOR O
 WHERE O.EXPLAIN_REQUESTER = SESSION_USER

UNION ALL

SELECT s.source_id
     , level + 1
     , tree.path || '/' || LPAD(CAST(s.source_id AS VARCHAR(3)), 3, '0')  path
     , tree.explain_time
     , POSITION('/' || LPAD(CAST(s.source_id AS VARCHAR(3)), 3, '0')  || '/' IN path USING OCTETS)
  FROM tree
     , SYSTOOLS.EXPLAIN_STREAM S
 WHERE s.target_id    = tree.operator_id
   AND s.explain_time = tree.explain_time
   AND S.Object_Name IS NULL
   AND S.explain_requester = SESSION_USER
   AND tree.cycle = 0
   AND level < 100
)
SELECT *
  FROM (
SELECT "Explain Plan"
  FROM (
SELECT CAST(   LPAD(id,        MAX(LENGTH(id))        OVER(), ' ')
            || ' | '
            || RPAD(operation, MAX(LENGTH(operation)) OVER(), ' ')
            || ' | '
            || LPAD(rows,      MAX(LENGTH(rows))      OVER(), ' ')
            || ' | '
            -- Don't show ActualRows columns if there are no actuals available at all
            || CASE WHEN COUNT(ActualRows) OVER () > 1 -- the heading 'ActualRows' is always present, so "1" means no OTHER values
                    THEN LPAD(ActualRows, MAX(LENGTH(ActualRows)) OVER(), ' ') || ' | '
                    ELSE ''
               END
            || LPAD(cost,      MAX(LENGTH(cost))      OVER(), ' ')
         AS VARCHAR(100)) "Explain Plan"
     , path
  FROM (
SELECT 'ID' ID
     , 'Operation' Operation
     , 'Rows' Rows
     , 'ActualRows' ActualRows
     , 'Cost' Cost
     , '0' Path
  FROM SYSIBM.SYSDUMMY1
-- TODO: UNION ALL yields duplicate. where do they come from?
UNION
SELECT CAST(tree.operator_id as VARCHAR(254)) ID
     , CAST(LPAD(' ', tree.level, ' ')
       || CASE WHEN tree.cycle = 1
               THEN '(cycle) '
               ELSE ''
          END    
       || COALESCE (
             TRIM(O.Operator_Type)
          || COALESCE(' (' || argument || ')', '')
          || ' '
          || COALESCE(S.Object_Name,'')
          , ''
          )
       AS VARCHAR(254)) AS OPERATION
     , COALESCE(CAST(rows AS VARCHAR(254)), '') Rows
     , CAST(ActualRows as VARCHAR(254)) ActualRows -- note: no coalesce
     , COALESCE(CAST(CAST(O.Total_Cost AS BIGINT) AS VARCHAR(254)), '') Cost
     , path
  FROM tree
  LEFT JOIN ( SELECT i.source_id
              , i.target_id
              , CAST(CAST(ROUND(o.stream_count) AS BIGINT) AS VARCHAR(12))
                || ' of '
                || CAST (total_rows AS VARCHAR(12))
                || CASE WHEN total_rows > 0
                         AND ROUND(o.stream_count) <= total_rows THEN
                   ' ('
                   || LPAD(CAST (ROUND(ROUND(o.stream_count)/total_rows*100,2)
                          AS NUMERIC(5,2)), 6, ' ')
                   || '%)'
                   ELSE ''
                   END rows
              , CASE WHEN act.actual_value is not null then
                CAST(CAST(ROUND(act.actual_value) AS BIGINT) AS VARCHAR(12))
                || ' of '
                || CAST (total_rows AS VARCHAR(12))
                || CASE WHEN total_rows > 0 THEN
                   ' ('
                   || LPAD(CAST (ROUND(ROUND(act.actual_value)/total_rows*100,2)
                          AS NUMERIC(5,2)), 6, ' ')
                   || '%)'
                   ELSE NULL
                   END END ActualRows
              , i.object_name
              , i.explain_time
         FROM (SELECT MAX(source_id) source_id
                    , target_id
                    , MIN(CAST(ROUND(stream_count,0) AS BIGINT)) total_rows
                    , CAST(LISTAGG(object_name) AS VARCHAR(50)) object_name
                    , explain_time
                 FROM SYSTOOLS.EXPLAIN_STREAM
                WHERE explain_time = (SELECT MAX(explain_time)
                                        FROM SYSTOOLS.EXPLAIN_OPERATOR
                                       WHERE EXPLAIN_REQUESTER = SESSION_USER
                                     )
                GROUP BY target_id, explain_time
              ) I
         LEFT JOIN SYSTOOLS.EXPLAIN_STREAM O
           ON (    I.target_id=o.source_id
               AND I.explain_time = o.explain_time
               AND O.EXPLAIN_REQUESTER = SESSION_USER
              )
         LEFT JOIN SYSTOOLS.EXPLAIN_ACTUALS act
           ON (    act.operator_id  = i.target_id
               AND act.explain_time = i.explain_time
               AND act.explain_requester = SESSION_USER
               AND act.ACTUAL_TYPE  like 'CARDINALITY%'
              )
       ) s
    ON (    s.target_id    = tree.operator_id
        AND s.explain_time = tree.explain_time
       )
  LEFT JOIN SYSTOOLS.EXPLAIN_OPERATOR O
    ON (    o.operator_id  = tree.operator_id
        AND o.explain_time = tree.explain_time
        AND o.explain_requester = SESSION_USER
       )
  LEFT JOIN (SELECT LISTAGG (CASE argument_type
                             WHEN 'UNIQUE' THEN
                                  CASE WHEN argument_value = 'TRUE'
                                       THEN 'UNIQUE'
                                  ELSE NULL
                                  END
                             WHEN 'TRUNCSRT' THEN
                                  CASE WHEN argument_value = 'TRUE'
                                       THEN 'TOP-N'
                                  ELSE NULL
                                  END  
                             WHEN 'SCANDIR' THEN
                                  CASE WHEN argument_value != 'FORWARD'
                                       THEN argument_value
                                  ELSE NULL
                                  END                    
                             ELSE argument_value    
                             END
                           , ' ') argument
                  , operator_id
                  , explain_time
               FROM SYSTOOLS.EXPLAIN_ARGUMENT EA
              WHERE argument_type IN ('AGGMODE'   -- GRPBY
                                     , 'UNIQUE', 'TRUNCSRT' -- SORT
                                     , 'SCANDIR' -- IXSCAN, TBSCAN
                                     , 'OUTERJN' -- JOINs
                                     )
                AND explain_requester = SESSION_USER
              GROUP BY explain_time, operator_id

            ) A
    ON (    a.operator_id  = tree.operator_id
        AND a.explain_time = tree.explain_time
       )
     ) O
UNION ALL
VALUES ('Explain plan (c) 2014-2017 by Markus Winand - NO WARRANTY - V20171102','Z0')
    ,  ('Modifications by Ember Crooks - NO WARRANTY','Z1')
    ,  ('http://use-the-index-luke.com/s/last_explained','Z2')
    ,  ('', 'A')
    ,  ('', 'Y')
    ,  ('Predicate Information', 'AA')
UNION ALL
SELECT CAST (LPAD(CASE WHEN operator_id = LAG  (operator_id)
                                          OVER (PARTITION BY operator_id
                                                    ORDER BY pred_order
                                               )
                       THEN ''
                       ELSE operator_id || ' - '
                  END
                , MAX(LENGTH(operator_id )+4) OVER()
                , ' ')
             || how_applied
             || ' '
             || predicate_text
          AS VARCHAR(100)) "Predicate Information"
     , 'P' || LPAD(id_order, 5, '0') || pred_order path
  FROM (SELECT CAST(operator_id AS VARCHAR(254)) operator_id
             , LPAD(trim(how_applied)
                  ,  MAX (LENGTH(TRIM(how_applied)))
                    OVER (PARTITION BY operator_id)
                  , ' '
               ) how_applied
               -- next: capped to length 80 to avoid
               -- SQL0445W  Value "..." has been truncated.  SQLSTATE=01004
               -- error when long literal values may appear (space padded!)
             , CAST(substr(predicate_text, 1, 80) AS VARCHAR(80)) predicate_text
             , CASE how_applied WHEN 'START' THEN '1'
                                WHEN 'STOP'  THEN '2'
                                WHEN 'SARG'  THEN '3'
                                ELSE '9'
               END pred_order
             , operator_id id_order
          FROM systools.explain_predicate p
         WHERE explain_time = (SELECT MAX(explain_time)
                                 FROM systools.explain_operator)
       )
)
ORDER BY path
);
EOF



3. 플랜 조회할 쿼리를 explain 뜬다.


db2 "explain plan for select * from sysibm.sysdummy1"



4. 오라클 스타일 플랜을 조회한다.

db2 "select * from last_explained"



Posted by in0de
,

MPP 환경의 hash partition table에서

잘못된 hash key 선정으로 인해 skew가 발생하는 현황을 조회하려면

다음 쿼리로 조회할 수 있다.


with COL as

(
    select
        tabschema
        , tabname
        , colname
        , colno
        , colcard
        , partkeyseq
        , remarks
    from syscat.columns
    where 1=1
    and partkeyseq > 0
)
select TABINF.tabschema, TABINF.tabname
, max(COL.remarks) as remarks
, substr(xmlcast(xmlgroup(', '||COL.colname as colnm order by COL.partkeyseq) as varchar(128)), 2) as "파티션 키 컬럼"
, max(TBL.remarks) as "컬럼 설명"
--, max(COL.partkeyseq) "파티션 키 순번"
, max(TBL.card) as "테이블 건수"
, max(COL.colcard) as "파티션 키 컬럼 distinct 개수"
, stddev((data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)/1024) as "표준편차_MB"
, stddev(data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size) / sum(data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size) * 1024 as "사이즈 고려 표준편차지수"
, sum((data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)/1024) as size_mb
, max(decode(dbpartitionnum, 0, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node0
, max(decode(dbpartitionnum, 1, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node1
, max(decode(dbpartitionnum, 2, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node2
, max(decode(dbpartitionnum, 3, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node3
, max(decode(dbpartitionnum, 4, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node4
, max(decode(dbpartitionnum, 5, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node5
, max(decode(dbpartitionnum, 6, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node6
, max(decode(dbpartitionnum, 7, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node7
, max(decode(dbpartitionnum, 8, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node8
, max(decode(dbpartitionnum, 9, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node9
, max(decode(dbpartitionnum, 10, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node10
, max(decode(dbpartitionnum, 11, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node11
, max(decode(dbpartitionnum, 12, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node12
, max(decode(dbpartitionnum, 13, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node13
, max(decode(dbpartitionnum, 14, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node14
, max(decode(dbpartitionnum, 15, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node15
, max(decode(dbpartitionnum, 16, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node16
, max(decode(dbpartitionnum, 17, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node17
, max(decode(dbpartitionnum, 18, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node18
, max(decode(dbpartitionnum, 19, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node19
, max(decode(dbpartitionnum, 20, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node20
, max(decode(dbpartitionnum, 21, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node21
, max(decode(dbpartitionnum, 22, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node22
, max(decode(dbpartitionnum, 23, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node23
, max(decode(dbpartitionnum, 24, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node24
, max(decode(dbpartitionnum, 25, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node25
, max(decode(dbpartitionnum, 26, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node26
, max(decode(dbpartitionnum, 27, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node27
, max(decode(dbpartitionnum, 28, data_object_p_size+index_object_p_size+long_object_p_size+lob_object_p_size+xml_object_p_size)) as node28
, max(TBL.lastused) as "테이블 마지막 사용일"
from SYSIBMADM.ADMINTABINFO TABINF
right join COL on TABINF.tabschema=COL.tabschema and TABINF.tabname=COL.tabname
right join syscat.tables TBL on TABINF.tabschema=TBL.tabschema and TABINF.tabname=TBL.tabname
where TABINF.tabtype='T'
group by TABINF.tabschema, TABINF.tabname
order by TABINF.tabschema, TABINF.tabname
;


hash key를 여러 칼럼으로 구성한 경우에 대해서는 결과가 제대로 안나올 수 있다.

수행 결과는 다음과 같으며


노드 간 데이터 분산 표준편차는 노드별로 고르지 않은 데이터 분포를 나타내는 값으로 크면 클 수록 노드별 분산이 잘 안되어있다는 의미이고


skew로 인해 발생하는 수행 속도 이슈나 용량 이슈는 테이블이 클 수록 영향이 크므로,

테이블의 용량 가중치를 준 '사이즈 대비 표준편차' 를 기준으로 hash key 재지정 대상을 선정한 후

업무적으로 변경이 가능한 지를 판단하면 되겠다.

Posted by in0de
,

데이터가 많은 테이블의 건 수를 조회하려고 할 때

SQL0802N
Arithmetic overflow or other arithmetic exception occurred.
산술 오버플로우 또는 다른 산술 예외가 발생했습니다.


위와 같은 오류가 발생할 수 있다.


이는, MAX_LONGINT_INT 제약 (2,147,483,647) 보다 더 많은 건 수를 담고 있는 테이블에

SELECT COUNT 문을 수행했을 경우 발생하며


이 때는 COUNT_BIG 함수를 사용하면 정상적으로 수행할 수 있다.


select count_big(*) from HUGE_TABLE;


한편, INT 타입의 컬럼을 SUM 하다보면 INT 타입의 크기 제약으로 인해 산술 오버플로우가 발생할 경우도 있는데

이런 경우에는 CAST를 해서 SUM 하면 된다.

 

select SUM(CAST(col1 as BIGINT)) from TABLE;

select SUM(CONVERT(bigint, col1)) from TABLE;

Posted by in0de
,

DPF 환경에서 오류 등으로 인해 특정 노드가 자동으로 재기동되어 올라왔을 때

모니터링 툴이 없다면 어느 노드에서 언제 문제가 발생하였는 지 확인하는 것도 쉽지 않다.

이럴 때 모든 노드의 db2diag.log를 일일이 확인해야 하는데, 그 작업량이 만만치 않다.


이런 경우 다음과 같이 조회하여 어느 노드에서 언제 재기동되었는 지 대략의 시간을 확인할 수 있다.


db2 "SELECT DBPARTITIONNUM, DB_CONN_TIME FROM SYSIBMADM.SNAPDB order by 1"

DBPARTITIONNUM DB_CONN_TIME             
-------------- --------------------------
             0 2015-03-04-14.39.12.711837
             1 2015-03-18-11.38.02.950709
             2 2015-03-18-11.38.02.950741
             3 2015-03-18-11.38.02.950723
             4 2015-03-18-11.38.02.950742
             5 2015-06-12-04.27.20.267942
             6 2015-06-12-04.27.24.363985
             7 2015-06-12-04.27.24.363985
             8 2015-06-12-04.27.24.364009
             9 2015-06-12-04.27.24.364020
            10 2015-06-12-04.27.24.364009
            11 2015-06-12-04.27.24.364009
            12 2015-06-12-04.27.24.364011
            13 2015-03-18-11.38.02.952040
            14 2015-03-18-11.38.02.951850
            15 2015-03-18-11.38.02.951862
            16 2015-03-18-11.38.02.951868
            17 2015-03-18-11.38.02.951868
            18 2015-03-18-11.38.02.951908
            19 2015-03-18-11.38.02.951870
            20 2015-03-18-11.38.02.951976
            21 2015-03-18-11.38.02.950909
            22 2015-03-18-11.38.02.950996
            23 2015-03-18-11.38.02.950994
            24 2015-03-18-11.38.02.951033
            25 2015-03-18-11.38.02.950951
            26 2015-03-18-11.38.02.951059
            27 2015-03-18-11.38.02.950974
            28 2015-03-18-11.38.02.951017


Posted by in0de
,

DB2 10.1.0.5 이하의 버전에서, 쿼리에

  • UNION ALL 이 있고,
  • LEFT JOIN 이 있고
  • LEFT JOIN되는 테이블 컬럼이 비교구문에 사용되는데, NULL 값이 일부 들어있는 경우

결과값이 비정상적으로 표시될 수 있다.


이는 다음 버그에 해당하며

IT08504: INCORRECT RESULT WHEN QUERY HAS LEFT OUTER JOIN AND UNION ALL


DB2 v10.1.0.5로 FixPack Update 하거나

쿼리 수행 전에 다음 문장을 추가하여 쿼리 옵티마이저를 변경하여 우회할 수 있다.

SET CURRENT QUERY OPTIMIZATION = 1;


Posted by in0de
,

DB2 database의 설치일자를 확인할 일이 있었는데,

db2 get db cfg 등에 존재하려나 하는 단순한 생각 같지는 않았다.


DB2 database의 설치일자를 확인하려면 다음 중 하나로 조회할 수 있다.


db2 connect to ${dbname}
db2 "select * from sysibm.sysversions"


db2 list history all for database ${dbname}


db2 "select create_time, tabname from syscat.tables where tabname like 'SYSTABLES'"


Posted by in0de
,

NetBackup 등의 서드파티 툴에 의해서 수행된 백업이라면 해당 GUI에서 종료하는 것이 옳겠다.


수행 중인 DB2 백업을 종료하기 위해서는 다음 쉘 커맨드를 수행하면 된다.


for apphandle in $(db2pd -d $db -applications -alldbpartitionnums | grep 'PerformingBackup' | awk '{print $2}')

do

db2 "force application ($apphandle)"

done

bash, DB2 DPF 10.1 에서 테스트 됨.

Posted by in0de
,

DB2 Favorite Links

DB2 LUW 2010. 9. 8. 17:52
db2Dean’s Favorite Links
아주 일목요연한 db2 link 모음
http://www.db2dean.com/Previous/DeanLinks.html

developerWorks: 다운로드
http://www.ibm.com/developerworks/kr/downloads/

IBM FixCentral
다운로드 하기 좋게 리뉴얼 됨
http://www-933.ibm.com/support/fixcentral/

Fix Packs for IBM DB2 and IMS Tools - DB2RE, PE, HPU
http://www-01.ibm.com/support/docview.wss?rs=434&uid=swg27008647

DMMag
이제 온라인으로 발간함
http://www.ibmdmmagazinedigital.com

IDUG
http://www.idug.org/

KDUG
나름 활성화 된 IBM 주도 DB2 커뮤니티
http://www.kdug.kr/

SQL limits
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0001029.htm

SQL and XML limits
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/r0001029.html

IBM Redbooks
필독서들. 읽을 시간은 있을 지?
http://www.redbooks.ibm.com/

IBM DB2 for Linux, Unix, and Windows Forum
http://www.ibm.com/developerworks/forums/forum.jspa?forumID=842&cat=19

Information Management Training : Self-Study Courses
http://www-01.ibm.com/software/data/education/selfstudy.html

DB2 Podcast series on channelDb2
http://www-01.ibm.com/software/sw-library/en_US/detail/R910330G45195P41.html

DB2 LUW DBA HowTo - Useful database administration techniques for Unix (LUW/UDB) DB2
http://www.ebenner.com/db2dba_blog/

developersWork search
사실, 찾아도 잘 안찾아지는 IBM의 검색 페이지.
http://www.ibm.com/developerworks/search/searchResults.jsp?searchType=1&searchSite=dW&searchScope=dW&query=&Search.x=28&Search.y=10&Search=Search

Everything You Wanted to Know About DB2 Universal Database Processes
http://www.ibm.com/developerworks/data/library/techarticle/0304chong/0304chong.html

IBM - DB2 사용자 게시판
한국 IBM이 관리하는. 어떻게 하면 이렇게 망할 수 있는 지?
http://www-903.ibm.com/kr/bbs/board_list.jsp?bbs=6

IBM - DB2 기술 정보
한국 IBM이 관리하는. 어떻게 하면 이렇게 업데이트가 없을 수 있는 지?
http://www-903.ibm.com/kr/techinfo/db2/

Migrating Recursive SQL from Oracle to DB2 UDB
http://www.ibm.com/developerworks/data/library/techarticle/0307steinbach/0307steinbach.html

Bringing the Power of Regular Expression Matching to SQL
http://www.ibm.com/developerworks/data/library/techarticle/0301stolze/0301stolze.html

Essential Facts about Index Covering in DB2 Universal Database
http://www.ibm.com/developerworks/data/library/techarticle/0303kuznetsov/0303kuznetsov.html

Improve DB2 query performance in a business intelligence environment - 튜닝 기술
http://www.ibm.com/developerworks/data/library/techarticle/dm-0703kapoor/

데이터 유형 간 캐스팅
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/r0008478.html

Lock events for DB2 for Linux, UNIX, and Windows, Part 1: Analyzing lockwait situations in DB2 for Linux, UNIX, and Windows
http://www.ibm.com/developerworks/data/library/techarticle/dm-0707fechner/index.html

Influence query optimization with optimization profiles and statistical views in DB2 9
http://www.ibm.com/developerworks/data/library/techarticle/dm-0612chen/

Making DB2 Case-Insensitive
http://www.ibm.com/developerworks/data/library/techarticle/0203adamache/0203adamache.html

dBforums - DB2
활발한 QnA, 문제를 검색하면 답변을 여기서 자주 얻기도 함
http://www.dbforums.com/db2/

DB2 SQL Cookbook Downloads Page
http://mysite.verizon.net/Graeme_Birchall/id1.html

An Expert's Guide to DB2 Technology
활발히 활동하는 블로거
http://it.toolbox.com/blogs/db2luw

Planet DB2
db2 blogger들의 메타 블로그
http://planetdb2.com/

Database Journal - DB2 Featured Database Articles
저널 형식의 짧은 특집, 기술 동향, 특집 컬럼
http://www.databasejournal.com/features/db2/

DBsarang - db2
http://database.sarang.net/?criteria=db2

DB2PORTAL Blog
http://db2portal.blogspot.com/

DB2uter
앞서가는 정보
http://www.ibmsystemsmag.blogs.com/db2utor/

깜장별 블로그
아마 엑셈에 근무하시는 db2 엔지니어이신 듯
http://bstar36.tistory.com/category/DB2

DB2ude
기술적인 내용을 다루는 블로그. 여기서도 해결책을 종종 찾을 수 있음.
http://www.db2ude.com/

추천 도서 리스트: Linux, UNIX, Windows용 DB2 UDB (한글)
쪼끔 오래되었으나 기본적인 내용들이기 때문에 언제 보아도 도움이 됨
http://www.ibm.com/developerworks/kr/library/dm-0509poon2/index.html

한국 데이터베이스 진흥원
이 조직이 정말 DB를 진흥해 주고 있는가?!
http://www.dpc.or.kr/

The Connection String Reference
DB Driver 연결 설정 스트링 참조 총망라
http://www.connectionstrings.com/

IBM Professional Certification Program
IBM 자격 시험 등록 페이지
https://www-903.ibm.com/kr/education/certify/index.html

IBM - IBM 자격증 로드맵
http://www-304.ibm.com/jct03001c/services/learning/ites.wss/kr/ko?pageType=page&c=a0013990

숭실대학교 Database lab
이상호 교수가 이끄는 팀. 2006년부터 DB2를 위주로 함
http://dblab.ssu.ac.kr/overview.html

DeveloperWorks - Best practices for DB2 for Linux, UNIX, and Windows
말이 필요 없는 Best Practices
http://www.ibm.com/developerworks/data/bestpractices/?S_TACT=105AGX11&S_CMP=LP

Bootcamps and Education
가고는 싶지만, 갈 수 없는...
http://www.ibm.com/developerworks/data/bootcamps

Instant SQL Formatter
SQL을 보기 좋게 만들어주는 온라인 툴. 상세한 설정은 없음.
http://www.dpriver.com/pp/sqlformat.htm

EXPORT command & File type modifiers for the export utility.
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.admin.cmd.doc/doc/r0008303.html

DB2 packages: Concepts, examples, and common problems
http://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0606chun/index.html

DB2 기초: 제약조건 (한글)
http://www.ibm.com/developerworks/kr/library/dm-0401melnyk/index.html

DB2 기초: 재미있는 날짜와 시간
의외로 자주 참조하게 됨
http://www.ibm.com/developerworks/kr/library/dm-0401melnyk/index.html

DB2 API
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.api.doc/doc/r0001915.html

DB2 9.5로 고가용성 구현하기
http://www.ibm.com/developerworks/kr/library/dm-0807wright/

DB2 UDB performance tuning scenarios: Part 1, DB2 UDB OLTP tuning illustrated with a Java program
http://www.ibm.com/developerworks/data/library/techarticle/dm-0508chong/

How multithreaded architecture works in DB2 9.5
http://www.ibm.com/developerworks/data/library/techarticle/dm-0807kharche/

Quest - Toad for DB2
토드 상용 버전의 홈페이지
http://www.quest.com/db2-on-luw/

토드 기간 한정 베타버전을 여기서 미리미리 구해서 쓸 수 있음
http://toadfordb2.com/index.jspa

DB2Monitor
아주 작은 db2top 대응 윈도우용 모니터링 툴
http://chuzhoi_files.tripod.com/

Posted by in0de
,