'2009/09'에 해당되는 글 5건

  1. 2009.09.30 볼륨매니저는 역사 속으로 (12)
  2. 2009.09.28 Temp Table Transformation (5)
  3. 2009.09.16 SQL 튜닝이 불가한 경우 (12)
  4. 2009.09.10 스칼라 서브쿼리를 서브쿼리로 변환하라 (11)
  5. 2009.09.04 오랜만의 책장 정리 (10)

추가적인 정보가 있으니 댓글을 반드시 확인하세요.(2009.10.01)

이젠 Oracle11g R2의 시대
2010
년도부터 본격적으로 프로젝트시 Oracle11g R2를 선택하게 될 것이다. Oracle11g R2의 장점은 이미 많이 알려져 있다. 신기능은 수도 없이 많지만 대표적인 것들을 소개하면 아래와 같다.

Top 10 Oracle 11gR2 New Features

Edition-Based Redefinition

 

DVM은 필수다
이러한 장점에도 불구하고 치명적일 수 있는 점을 소개한다. 그것은 볼륨매니저를 더 이상 사용할 수 없다는 것이다. Oracle11g R2부터 RAC를 사용할 경우 DVM(ASM Dynamic Volume Manager)을 반드시 사용해야만 한다. 기존의 볼륨매니저를 사용할 수 있는 방법이 있는데 그것은 Oracle11g R2를 바로 설치하는 대신에 Oracle11g R1 에서 Oracle11g R2로 업그레이드하는 방법이 있다. 하지만 이것은 어디까지나 트릭이며 추천할 것은 못 된다.

 

기존의 베리타스등의 Third Party 볼륨매니저는 버려야 하나?

이것은 일종의 끼워팔기 인가?
이젠 Raw Device 대신 ACFS(ASM Cluster File System)을 사용해야 하나?

어찌되었건 내년부터 본격적인 ASM의 시대가 될것이다.



신고

'Oracle > News' 카테고리의 다른 글

볼륨매니저는 역사 속으로  (12) 2009.09.30
오라클은 몇년이나 갈까?  (4) 2009.07.31
Science of DataBase 1주년  (22) 2009.07.02
오라클 공룡기업으로 거듭나는가?  (0) 2009.04.21
Posted by extremedb

댓글을 달아 주세요

  1. Favicon of http://ukja.tistory.com BlogIcon 욱짜 2009.10.01 09:05 신고  댓글주소  수정/삭제  댓글쓰기

    RAC에서 ASM(+Dynamic Volume Manager)을 사용하는 것이 필수가 되었나요? 조금 의왼데요.

    혹시 원문 주소를 알 수 있을까요? New Feature 매뉴얼을 봐도 필수인지 여부가 명확하게 설명되어 있지 않은거 같아서요.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.10.01 09:44 신고  댓글주소  수정/삭제

      작년에 이소식을 접했는데 아주 놀란 기억이 있습니다.
      이번에 11.2 에서는 공식적인 문서가 발표되었습니다.
      제목 : Announcement on using Raw devices with release 11.2
      문서번호 : 754305.1

      다들 11g R2 새기능에 열광하고 있지만 이러한 문제를 고민해 봐야 할것입니다.

  2. Favicon of http://ukja.tistory.com BlogIcon 욱짜 2009.10.01 10:03 신고  댓글주소  수정/삭제  댓글쓰기

    원문에 대해 오해가 조금 있는데요. ASM이 필수가 된 것이 아니라 Raw Device를 지원하지 않겠다는 의미로 생각됩니다.

    정리를 해보니까 다음과 같습니다.

    - DBCA를 통해 Oracle 11gR2 데이터베이스를 설치하는 경우에 한해서 Raw Device를 지원하지 않는다.
    - 그 외에 경우에는 여전히 Raw Device를 사용할 수 있다. 즉, 업그레이드를 하거나 Command Line을 통해 설치하는 경우에는 Raw Device를 사용할 수 있다.
    - DBCA를 통해 Oracle 11gR2 데이터베이스를 설치할때는 Raw Device가 아닌 ASM, File System, NFS, Clustered File System(RAC), NFS(RAC)를 사용해야 한다.

    한마디로 말하면 Raw Device를 ASM이 완전히 대체하는 형식이 되네요.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.10.01 10:18 신고  댓글주소  수정/삭제

      오해가 아닙니다.
      기존에 Raw Device 를 관리하던것이 베리타스 등의 볼륨매니져 입니다. 이제는 ASM 을 써야 하므로 그것이 필요 없어진 것이고 당연히 DVM 을 써야 하겠죠.
      아래의 글을 보면 DBCA와는 상관없이 RAC 에서 Raw Device 를 지원하지 않는것 같습니다.
      RAC database files must be stored on ASM, a certified clustered file system, or a certifed NFS filer.
      더불어 미래에 Oracle V12 나 V13 을 사용하게 될텐데 oracle11.1 을 설치하고 다시 V12 로 업그레이드 하는것은 아주 비효율적이므로 사용하지 못할거 같습니다.

  3. Favicon of http://ukja.tistory.com BlogIcon 욱짜 2009.10.01 10:38 신고  댓글주소  수정/삭제  댓글쓰기

    한국 오라클로부터 공식적인 의견을 들었으면 좋겠네요.

    베리타스 등의 공인된 3rd Party File System과 Volume Manager는 여전히 사용가능한 것으로 생각됩니다. 즉 ASM이 아니라 Veritas File System이나 Veritas Clustered File System(RAC)도 여전히 사용가능하죠? 즉 ASM이 필수는 아니고 Raw Device를 사용할거면 앞으로는 ASM을 사용하라는 정도의 의미가 아닐까 합니다.


    아래 부분을 보면 CREATE DATABASE, TABLESPACE 명령을 이용하는 경우에는 11gR2에서도 여전히 Raw Device를 사용할 수 있는 것으로 명시되고 있습니다.

    Customers who wish to create 11.2 databases on RAW must use the command line interfaces to create datafiles on RAW (i.e., CREATE DATABASE/TABLESPACE). Alternatively, they can create an 11.1 database and upgrade it to 11.2.

    아마도 이것은 RAC에서도 마찬가지일것으로 생각됩니다.

    그리고 문서로 보면 Release 12에서는 어떤 형태로든 Raw Device가 완전히 Desupport되는 것으로 예고하고 있네요. 그 때까지는 시간이 많기 때문에(3-4년 정도) 차근차근 Raw Device를 ASM이나 Veritas File System으로 옮기는 작업이 이루어질 것 같습니다.

    그리고 ASM DVM은 말 그대로 Volume Manager때문에 아마 ASM DVM위에 ASM Cluster File System이 아닌 Veritas File System을 얹는 것도 이론적으로 가능할 것 같습니다. ASM이 확산된다면 ASM용 File System도 상업적으로 개발가능할 거 같습니다. ASM이 얼마나 확산되느냐가 관건인데 강력한 3rd Party들과의 경쟁이 있을거 같습니다.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.10.01 10:57 신고  댓글주소  수정/삭제

      물론 그럴수 있습니다.
      하지만 현실적으로 대부분의 경우 File System은 성능상 사용하지 않습니다. 대부분의 경우 Raw Device를 사용하지요.또한 Raw Device의 관리용도로 볼륨매니져를 사용하는 것이구요. 물론 File System의 성능이 현재 Raw Device를 많이 따라온 것은 사실입니다. 11.2 에서 V12 로 가는 중간단계로서 마지막 으로 Raw Device를 지원한다면 앞으로 약 3~4년간은 문제가 없을것 같습니다.

      제가 쓴글이 명확하지 않아서 오해가 생긴것 같습니다.

  4. jikoo11@hanmail.net 2009.10.01 11:19 신고  댓글주소  수정/삭제  댓글쓰기

    Oracle 12G Release 부터는 아예 ASM을 사용하여야 하지만, 아직 11GR2에서는 일반 CFS(Veritas, GPFS...)를 사용 가능합니다.
    Trick으로 Script로 DB를 만들거나, 11G Realease 1이하 버전에서의 DB Upgrade의 방법으로는 Raw Device의 사용이 가능합니다. 아마 11G Release 2의 ASM 기능 및 ASM DVM 등은 12G의 기능을 위한 사전단계가 아닌가 싶습니다. 그리고, ASM도 나온지 거의 10년이 되어 갑니다. 이제는 많이 안정적이지 않을지 생각합니다. 따지고 보자면요...

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.10.01 12:39 신고  댓글주소  수정/삭제

      문제의 핵심은 OCR 입니다. Raw Device의 정보는 OCR 에 등록 되질 못하죠. 이문제 때문에 11.1 에서 11.2 로 UPGRADE 하는 편법을 사용한거 같습니다. 기존의 11.1 에서는 OCR 정보가 미리 있으므로 UPGRADE 시에 이전 정보를 그대로 사용할수 있죠. 따라서 시스템이 RAC인지 아닌지가 이주제에 관련해서 굉장히 중요해질 것입니다.

  5. ikoo11@hanmail.net 2009.10.01 12:46 신고  댓글주소  수정/삭제  댓글쓰기

    위의 제가 쓴 글은 RAC일 경우를 말한건데, 제가 RAC라고 표기를 안했군요... 그리고, 설치시 OUI에서 ASM, CFS를 고를 수 있는 단계가 있으며, CRS, ASM은 Grid Infrastructure라는 것으로 통합되어져서 설치가 됩니다. 그리고, Grid Infrastructure 설치시에 4가지 Option이 있는데, 그것에서 선택하여 설치가 가능합니다.
    아마 Option은

    1. Grid Infrastructure for a Cluster
    2. Grid Infrastructure for a Standalone Server
    3. Grid Infrastructure Software Only (ADVANCED)
    4. Upgrade from a previous versin of Oracle Clusterware and ASM

    그리고, 위의 단계에서 1을 선택하여 설치시에 CFS를 선택하여 설치할 수 있도록 되어 있습니다.
    Standalone Server에서 Grid Infrastructure 선택이 있는것으로 보아서는 RAC ONE이라는 Option과 관련이
    있는것으로 보이네요. 더 살펴봐야 하겠지만요...

  6. ikoo11@hanmail.net 2009.10.01 13:04 신고  댓글주소  수정/삭제  댓글쓰기

    사족으로 아마도 11월이면, UNIX용 11G Release 2가 나온다고 하네요...

오라클 Transformer 때때로 반복작업이 일어날경우 같은 테이블에 대한 부하가 심해지므로 TEMP 테이블을 만들어서 저장하고 테이블을 이용하여 반복적인 작업을 하게되는 경우가 있다. 대표적인 경우가 GROUPING SETS 사용하는 경우이다.

SELECT department_id, JOB_ID, AVG (salary) avg_sal

  FROM employee a

GROUP BY GROUPING SETS(department_id, JOB_ID)   ;

 

---------------------------------------------------------------+---------------------------+

| Id  | Operation                   | Name                     | Rows  | Cost  | Time      |

---------------------------------------------------------------+---------------------------+

| 0   | SELECT STATEMENT            |                          |       |    11 |           |

| 1   |  TEMP TABLE TRANSFORMATION  |                          |       |       |           |

| 2   |   LOAD AS SELECT            |                          |       |       |           |

| 3   |    TABLE ACCESS FULL        | EMPLOYEE                 |   107 |     3 |  00:00:01 |

| 4   |   LOAD AS SELECT            |                          |       |       |           |

| 5   |    HASH GROUP BY            |                          |     1 |     3 |  00:00:01 |

| 6   |     TABLE ACCESS FULL       | SYS_TEMP_0FD9D6608_434CFB|     1 |     2 |  00:00:01 |

| 7   |   LOAD AS SELECT            |                          |       |       |           |

| 8   |    HASH GROUP BY            |                          |     1 |     3 |  00:00:01 |

| 9   |     TABLE ACCESS FULL       | SYS_TEMP_0FD9D6608_434CFB|     1 |     2 |  00:00:01 |

| 10  |   VIEW                      |                          |     1 |     2 |  00:00:01 |

| 11  |    TABLE ACCESS FULL        | SYS_TEMP_0FD9D6609_434CFB|     1 |     2 |  00:00:01 |

---------------------------------------------------------------+---------------------------+

 

위의 PLAN 보면 먼저 ID 기준으로 3번에서 employee 테이블을 읽어서 필요한 컬럼만 TEMP 테이블에 저장해두고 그테이블을 반복해서 이용(ID 기준으로 6, 9, 11)하게 되는것이다. 그렇다면 3번이나 반복해서 temp 테이블을 사용하는걸까?

해답은 10053 trace 있다. id 기준으로 6번에 해당하는 SQL 아래와 같다. 

SELECT  /*+  */ NULL C0, C1 C1, BIN_TO_NUM(1, GROUPING(C1)) D0, COUNT(A0), SUM(A0)  FROM "SYS"."SYS_TEMP_0FD9D6608_434CFB" GROUP BY (C1)

 

위에서 C0, C1 TEMP 테이블의 컬럼 ALIAS 이며 각각 department_id, JOB_ID 의미한다. 또한 BIN_TO_NUM 함수를 사용한 이유는 나중에 ID 기준으로 11번째 에서 Group by 단위를 알아내기 위함이다. COUNT(A0), SUM(A0) select 한이유도 11번에서 AVG (salary) 값을 구하기 위해서이다. 참고로 avg(col1) 함수는 논리적으로 sum(col1)/count(col1) 같다.

또한 id 기준으로 9번에 해당하는 SQL 아래와 같다. 

SELECT  /*+  */ C0 C0, NULL C1, BIN_TO_NUM(GROUPING(C0), 1) D0, COUNT(A0), SUM(A0)  FROM "SYS"."SYS_TEMP_0FD9D6608_434CFB" GROUP BY (C0)

 
최종적으로 Transformation이 적용된 SQL은 다음과 같다.

with SYS_TEMP_0FD9D6608_434CFB as
   (
   SELECT department_id AS C0, JOB_ID AS C1, salary AS A0
     FROM employee a
   )  ,
   TEMP1 as
   (
    SELECT NULL C0, C1, COUNT(salary) AS A1, SUM(salary) AS A0
     FROM SYS_TEMP_0FD9D6608_434CFB
    GROUP BY C1
   ) ,
   TEMP2 as
   (
    SELECT C0, NULL C1, COUNT(salary) AS A1, SUM(salary) AS A0
     FROM SYS_TEMP_0FD9D6608_434CFB
    GROUP BY C0
   ) ,
  SYS_TEMP_0FD9D6609_434CFB AS
  (
   SELECT TEMP1. * FRPM TEMP1
   UNION ALL
   SELECT TEMP1. * FRPM TEMP1
  )
SELECT C0 AS DEPARTMENT_ID, C1 AS JOB_ID, A0 AS AVG_SAL
  FROM (SELECT C0, C1,
                       DECODE(A0, 0, TO_NUMBER(NULL), A1/A0) AS A0 --> 분모가 0 일 경우 처리
              FROM SYS_TEMP_0FD9D6609_434CFB )  ;



불만

id
기준으로 6번과 9번에서 각각 job_id department_id group by 해놓고 이것을 id 11 번에서 합쳐서 보여주게 된다. 하지만 필자는 이런 변환에 대하여 불만이 있다. 위의 쿼리는 EMPLOYEE 테이블을 GROUP BY 하지 않은 상태로 TEMP 테이블에 적재한다. 이것은 매우 비효율적이다. EMPLOYEE 테이블을 Temp 테이블에 적재시 미리 Group BY 하여 넣을 수가 있다. 아래의 SQL 처럼 미리 GROUP BY 하여 건수를 미리 줄여놓으면 반복작업시의 부하가 획기적으로 줄어들수 있기 때문이다.


select  department_id, JOB_ID, sum(sum_sal) / sum(cnt) as avg_sal 

from  (SELECT department_id, JOB_ID, count(salary) cnt, sum(salary) sum_sal

           FROM employee a

          GROUP BY department_id, JOB_ID  )

GROUP BY GROUPING SETS(department_id, JOB_ID)   ;

 

이렇게 수동으로 SQL 바꾸는 방법은 Grouping Sets 변환로직이 변하지 않는한 확실한 튜닝방법이 될수 있으므로 반드시 고려되어야 한다.

신고
Posted by extremedb

댓글을 달아 주세요

  1. feelie 2009.09.28 19:27 신고  댓글주소  수정/삭제  댓글쓰기

    20여일 동안 기다리고 기다렸습니다.

    그동안 많이 바쁘셨던 모양이네요..

    오늘도 좋은 내용 잘 봤습니다. 그런데 하나 궁금한 점이 있습니다.
    내용중에
    "id 기준으로 6번과 9번에서 각각 job_id 와 department_id 로 group by 해놓고 이것을 id 11 번에서 합쳐서 보여주게 된다." 라고 하셨는데

    id 6,9 각각 temp 테이블(SYS_TEMP_0FD9D6608_434CFB)을 사용하고, 결과를 합해서 SYS_TEMP_0FD9D6609_434CFB 테이블에 저장하고 id 11에서 이것을 액세스해서 뷰로 만들고 select 하는것가요?

    실행계획 순서로 헷갈리고, ID 기준으로 : 3->2->1->6->5->4->9->8->7->11->10->1 이런 순서인가요?

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.29 11:52 신고  댓글주소  수정/삭제

      네 말씀 하신대로 6번과 9번에서 각각 수행된 쿼리를 union 하여 SYS_TEMP_0FD9D6609_434CFB 테이블에 저장 하고 이것을 11번에서 사용하는 것입니다. 이것은 GROUPING SET 이 기본적으로 UNION 을 적용하기 때문에 그렇습니다.
      최종 SQL 은 다음과 같습니다.

      SELECT /*+ CARDINALITY( 107) */ "sys_view_v"."C0" "DEPARTMENT_ID","sys_view_v"."C1" "JOB_ID","sys_view_v"."A0" "AVG_SAL"
      FROM (SELECT /*+ NO_MERGE NO_PUSH_PRED(v) */ C0, C1, DECODE(A0, 0, TO_NUMBER(NULL), A1/A0) AS A0
      FROM ( SELECT "SYS"."SYS_TEMP_0FD9D661C_25E901".*
      FROM "SYS"."SYS_TEMP_0FD9D661C_25E901" --> UNION 적용된 SQL
      ) v
      ) "sys_view_v"

      그리고 수행순서는 3->2->6->5->4->9->8->7->11->10->1->0 입니다. 이유는 11번에서도 TEMP TABLE 을 사용하기 때문에 그렇습니다.

  2. feelie 2009.09.29 12:33 신고  댓글주소  수정/삭제  댓글쓰기

    감사합니다.

  3. feelie 2009.10.16 13:42 신고  댓글주소  수정/삭제  댓글쓰기

    지난번에 한번보고 오늘다시 보다가 궁금한점이 있습니다.
    테스트를 해서 시간을 비교해보면 먼저 group by후 처리하는부분이 제일 빠를것 같은데요.
    테스트를 해보면 더 늦게 나옵니다.
    1. 00:00:00.11
    2. 00:00:00.37
    3. 00:00:00.21
    데이터의 양에 적어서 그런것인지,A_TIME만으로판단하면 안되는것인지요?
    환경 : 10.2.3.0
    데이터량 : 80000

    1. union all
    ---------------------------------------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
    ---------------------------------------------------------------------------------------------------------------------------------
    | 1 | VIEW | | 1 | 35 | 700 | 684 (4)| 00:00:09 | 38 |00:00:00.11 | 3018 |
    | 2 | UNION-ALL | | 1 | | | | | 38 |00:00:00.11 | 3018 |
    | 3 | HASH GROUP BY | | 1 | 21 | 84 | 342 (4)| 00:00:05 | 23 |00:00:00.11 | 1509 |
    | 4 | TABLE ACCESS FULL| TB_TESTLOGHIST | 1 | 73839 | 288K| 335 (2)| 00:00:05 | 74084 |00:00:00.01 | 1509 |
    | 5 | HASH GROUP BY | | 1 | 14 | 56 | 342 (4)| 00:00:05 | 15 |00:00:00.09 | 1509 |
    | 6 | TABLE ACCESS FULL| TB_TESTLOGHIST | 1 | 73839 | 288K| 335 (2)| 00:00:05 | 74084 |00:00:00.01 | 1509 |
    ---------------------------------------------------------------------------------------------------------------------------------


    2. grouping sets
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | 1 | TEMP TABLE TRANSFORMATION | | 1 | | | | | 38 |00:00:00.37 | 1944 | 134 | 134 | | | |
    | 2 | LOAD AS SELECT | | 1 | | | | | 1 |00:00:00.17 | 1646 | 0 | 132 | 525K| 525K| 525K (0)|
    | 3 | TABLE ACCESS FULL | TB_TESTLOGHIST | 1 | 73839 | 576K| 335 (2)| 00:00:05 | 74084 |00:00:00.01 | 1509 | 0 | 0 | | | |
    | 4 | LOAD AS SELECT | | 1 | | | | | 1 |00:00:00.10 | 142 | 132 | 1 | 265K| 265K| 265K (0)|
    | 5 | HASH GROUP BY | | 1 | 1 | 5 | 3 (34)| 00:00:01 | 23 |00:00:00.08 | 138 | 132 | 0 | | | |
    | 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6744_BD323BAA | 1 | 1 | 5 | 2 (0)| 00:00:01 | 74084 |00:00:00.01 | 138 | 132 | 0 | | | |
    | 7 | LOAD AS SELECT | | 1 | | | | | 1 |00:00:00.10 | 140 | 0 | 1 | 265K| 265K| 265K (0)|
    | 8 | HASH GROUP BY | | 1 | 1 | 5 | 3 (34)| 00:00:01 | 15 |00:00:00.08 | 135 | 0 | 0 | | | |
    | 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6744_BD323BAA | 1 | 1 | 5 | 2 (0)| 00:00:01 | 74084 |00:00:00.01 | 135 | 0 | 0 | | | |
    | 10 | VIEW | | 1 | 1 | 23 | 2 (0)| 00:00:01 | 38 |00:00:00.01 | 7 | 2 | 0 | | | |
    | 11 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6745_BD323BAA | 1 | 1 | 23 | 2 (0)| 00:00:01 | 38 |00:00:00.01 | 7 | 2 | 0 | | | |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    3. group by 후 grouping sets
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | 1 | TEMP TABLE TRANSFORMATION | | 1 | | | | | 38 |00:00:00.21 | 1547 | 3 | 3 | | | |
    | 2 | LOAD AS SELECT | | 1 | | | | | 1 |00:00:00.16 | 1513 | 0 | 1 | 265K| 265K| 265K (0)|
    | 3 | HASH GROUP BY | | 1 | 208 | 1664 | 342 (4)| 00:00:05 | 30 |00:00:00.14 | 1509 | 0 | 0 | | | |
    | 4 | TABLE ACCESS FULL | TB_TESTLOGHIST | 1 | 73839 | 576K| 335 (2)| 00:00:05 | 74084 |00:00:00.07 | 1509 | 0 | 0 | | | |
    | 5 | LOAD AS SELECT | | 1 | | | | | 1 |00:00:00.02 | 10 | 1 | 1 | 265K| 265K| 265K (0)|
    | 6 | HASH GROUP BY | | 1 | 1 | 18 | 3 (34)| 00:00:01 | 23 |00:00:00.01 | 6 | 1 | 0 | | | |
    | 7 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6746_BD323BAA | 1 | 1 | 18 | 2 (0)| 00:00:01 | 30 |00:00:00.01 | 6 | 1 | 0 | | | |
    | 8 | LOAD AS SELECT | | 1 | | | | | 1 |00:00:00.02 | 8 | 0 | 1 | 265K| 265K| 265K (0)|
    | 9 | HASH GROUP BY | | 1 | 1 | 18 | 3 (34)| 00:00:01 | 15 |00:00:00.01 | 3 | 0 | 0 | | | |
    | 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6746_BD323BAA | 1 | 1 | 18 | 2 (0)| 00:00:01 | 30 |00:00:00.01 | 3 | 0 | 0 | | | |
    | 11 | VIEW | | 1 | 1 | 23 | 2 (0)| 00:00:01 | 38 |00:00:00.01 | 7 | 2 | 0 | | | |
    | 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6747_BD323BAA | 1 | 1 | 23 | 2 (0)| 00:00:01 | 38 |00:00:00.01 | 7 | 2 | 0 | | | |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.10.17 23:35 신고  댓글주소  수정/삭제

      데이터의 건수가 적을때는 시간으로 판단하는것은 효율을 알기가 힘듭니다. 따라서 가장 좋은 방법은 Buffers 와 Used-Mem 가 가장 적게 드는것으로 판단 하시면 됩니다.
      1번의 Union all 이 가장 빠른 이유는 Temp 테이블에 데이터를 Load 하는 작업이 없기 때문입니다. 2번은 Loading 작업이 있지요.

SQL 튜닝시의 업무적 접근
SQL
튜닝시 Buisiness 관점으로 접근하는 것은 매우 중요한 일이다. 예를 들면 SQL 아무리 튜닝을 해도 해결되지 않는 경우가 있다. 당신이 아무리 화려한 튜닝 테크닉을 가지고 있다고 해도 말이다. 이런 경우 발상을 전환하는 것이 필요하다. SQL 튜닝을 하지않고 이슈를 해결해야 한다는 이다. 튜닝시 이슈가 가장 많이 발생하는 3가지 경우를 소개한다.

조회조건은
제약이 필요없나?
웹화면에서 조회조건으로 일자 From ~ To 조건으로 주는 경우가 다반사이다. 사용자는 많은 기간을 조회하고 싶어한다. 실제로 10년간의 거래내역집계를 조회하는 경우도 보았다. 이런 경우는 반드시 화면에서 기간의 제한을 두어야 한다. 한달로 제한 한다든지 아니면 일주일로 한다든지 상황에 따라서 얼마든지 제약을 줄수 있다. 조회조건 선택시 Combo Box Drop Down List Box 에서 전체보기를 없앤다면 마찬가지로 성능향상을 기대할수 있다. 개발자와의 대화 혹은 화면분석이 필요한 순간이다. 필자는 이러한 작업들을 튜닝 프로젝트시에 반드시 실행해야하는 필수 과정으로 생각한다. 이러한 과정을 사용자 화면 튜닝으로 정의 해야한다.

집계 테이블은 필요한가?
다른 예제는 SQL 집계(Group By + Count) 하는 경우 아무리 튜닝을 해보아야 느릴수 밖에 없다. 가장 좋은 것은 회의를 통하여 이러한 화면들을 DW시스템으로 넘기는 것이다. 이것은 어느정도의 정치력이 필요하다. 주장하는 사람의 권위와 Power 필요하다는 이야기 이다. 하지만 이것이 안될경우 업무팀과 협의 하여 집계 테이블을 만들어야 한다. 집계테이블은 최소화 시켜야 한다. 예를 들어 년별, 지점별 집계 SQL 있고 월별 지점별 집계 SQL 있다면 집계 테이블은 월별로 하나만 만들어야 한다. 집계 테이블이 많아지면 정합성을 저해할수 있다.

 

저작의도를 알면 길이 보인다
계약
테이블과 고객 테이블을 불필요하게 조인 하는 SQL 있었다. 하지만 조인만 하고 Select 절에서는 고객 테이블의 컬럼이 하나도 없었다. 상식적으로 보면 계약테이블의 고객번호는 100% 고객 테이블에 있어야 한다. 그렇다면 고객 테이블을 From 절에서 삭제 하면 될까? 아주 위험한 발상이다. 특수한 SQL 경우에는 검증용 SQL 프로그램으로 만들기도 한다. 이러한 경우 방법은 한가지이다. SQL 작성한 개발자에게 질문하여 이것이 계약 테이블의 고객번호를 검증하기 위한 SQL 인지 물어보는 것이다. 경험상 대부분의 경우 불필요한 조인을 삭제할수 있었다. 이러한 상황은 특히 개발자들 끼리 SQL Copy 약간 수정하여 사용하는 경우 많이 발생 하게된다.

회의나 대화도 중요한 튜닝 Skill 이라는 점
여러분은
위의 3가지 경우를 어떻게 생각하는가? 튜닝의 기술적인 Skill 아니므로 무시하고 넘어가는 경우를 많이 보아왔다. 절대 문제를 해결할수 없으며 문제를 키울 뿐이다. 이렇게 되지 않으려면 튜닝시에 사용자 혹은 개발자와 자주 회의를 가져야 한다. 경험상 대화를 자주 할수록 문제의 해결 혹은 대안을 빨리 찾는 경우가 많았다. 이때 고객과의 대화의 기술 혹은 설득의 기술이 많은 도움이 된다. 이러한 기술들은 튜닝 자체의 Skill 보다 상위의 개념이며 문제를 해결할 경우 팀원이나 직원들에게 존경을 받거나 부러움의 대상이 가능성이 크다.


결론:
실제로 SQL 튜닝 등으로 성능향상이 불가능한 경우는 당신이 생각하는 것 보다 훨씬 많다.
이럴 경우 화려한 튜닝 테크닉으로 문제를 해결을 시도하는 사람, 대화와 설득으로 해결하는 사람 누가 더 뛰어난 튜너인가?



신고
Posted by extremedb

댓글을 달아 주세요

  1. 혈기린 2009.09.16 10:45 신고  댓글주소  수정/삭제  댓글쓰기

    가장 어려운 튜닝은 사실 고객을튜닝(?) 하는것일지도 모르겠네요
    꽉막히고 고집센 현업을 만나면 ~~~ 설득의 기술 대화와 협상의 기술이 필요할지도 ㅎㅎ
    좋은글 매번 감사 드립니다 ^^

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.16 12:44 신고  댓글주소  수정/삭제

      공감 합니다.^^
      말씀 하신대로 대화의 기술은 튜닝 뿐만 아니라 인생전체에 대해서도 영향을 끼치니 반드시 익히는것이 좋겠죠.^^

  2. Favicon of http://blog.naver.com/xsoft BlogIcon 강정식 2009.09.16 11:24 신고  댓글주소  수정/삭제  댓글쓰기

    저도 동규님 포스팅에 공감을 표합니다.
    역시나 튜닝스킬로는 한계가 있고 업무 내용까지 아는것이 가장 좋다는 것을 요즘 많이 느끼고 있습니다.

    아마도 향후 튜닝이라 함은 'Application - Tech - Database - Module' 4개를 관통하는 서비스가 되지 않을까 싶습니다. 저 또한 'module-tech consultant'가 되는게 목표긴 하지만 너무 방대하기에 호흡을 길게 가져가고 있습니다.

    아마 동규님은 저보다 저 멀리서 먼저 걸어가시고 있으시니 힘드시더라도 뒤에서 여러사람들이 응원하고 있다는 것을 알아주시기 바랍니다. ^^

    그럼 오늘 하루도 행복하세요~

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.16 12:46 신고  댓글주소  수정/삭제

      성원에 감사드립니다.
      4가지를 관통하는 튜닝은 앞으로 대세가 될거 같습니다.
      그렇게 하려면 APM TOOL 이 우선적으로 도입되어야 겠죠.
      제니퍼 같은 APM 툴은 상당히 유용하다고 들었습니다.
      좋은하루 되세요.

  3. 만두돌이 2009.09.16 21:52 신고  댓글주소  수정/삭제  댓글쓰기

    좋은글 감사합니다.
    자주 들릴께요 ^^;

  4. feelie 2009.09.16 22:06 신고  댓글주소  수정/삭제  댓글쓰기

    가끔 기술적인 부분에서 벗어나 데이터 이외의 고려사항까지 기술해주시니 감사할 딸름입니다.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.16 22:22 신고  댓글주소  수정/삭제

      말씀 하신대로 기술로 해야할것과 대화로 풀어야 할 것을 잘 분별 하는것이 핵심이라고 할수 있겠네요.
      늦은밤에도 열심히 하시네요.
      좋은밤 되세요.

  5. 금땡이 2009.09.18 11:08 신고  댓글주소  수정/삭제  댓글쓰기

    중요한 통찰 입니다.
    많이 바쁘신 줄 알지만 이러한 내용들이 이 블로그를 방문하는 다양한 분들에게 도움이 될 것 같습니다.
    잠을 줄여서라(^^)도 글을 많이 올려 주시면 합니다.

    이미 님은 혼자의 몸이 아닌 것 같습니다. 건강에 유념하시기를....

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.18 11:33 신고  댓글주소  수정/삭제

      오랜만 입니다.
      '잠을 줄여서라도 글을 올려라' 는 말에 동감합니다.
      노력해 보겠습니다.
      현재는 매일 5시간 정도 수면을 취하고 있습니다.
      좋은 하루 되세요.

  6. 호야 2009.09.21 18:10 신고  댓글주소  수정/삭제  댓글쓰기

    포스팅에 공감이 가네요..

    아직도 튜너를 신으로 알고 일단 해보라고 하는 고객이 이미 다 제한할것은 했다고 하고 업무를 변경안하려는 하는데

    커뮤니케이션 스킬이 절대적으로 필요하더군요.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.21 18:19 신고  댓글주소  수정/삭제

      네 맞습니다.
      경험상 거의 1/3 의 경우에 튜너 혼자 해결하지 못하는 경우가 발생 하더군요. 말씀 하신것 처럼 이럴경우는 대화로 문제를 해결하는 것이 가장 좋은 방법이 되겟네요.
      좋은 하루 되세요.^^

개발자의 질문
개발자 한명이 DBA 에게 질문을 던졌다. ‘스칼라 서브쿼리를 사용한 SQL 인라인뷰로 싸고 인라인뷰 외부에서 스칼라 서브쿼리를 Filter 조건으로 사용하면 스칼라 서브쿼리가 없어지는 현상이 발생합니다. 현상이 정상인가요?’  그런데 DBA 그런일은 발생할 수가 없다고 하였다. 과연 사실일까? 정답은 스칼라 서브쿼리가 없어진다는 것이다. 예리한 눈을 가진 개발자 임에 틀림없다.

 

백견이 불여일행
SSTS( Scalar Subquery To Subquery )
스칼라 서브쿼리를 서브쿼리로 변경시키는 Transformation 과정이다. 하지만 항상 변환되지 않는다. 스칼라 서브쿼리를 인라인뷰 외부에서 Filter 조건으로 사용할때만 가능하다. 아래의 SQL 보자

인덱스 상황 :

EMP_JOB_IX : employee (job_id)

DEPT_ID_PK1 : department(department_id)

SELECT a.employee_id, a.first_name, a.last_name, a.email

  FROM (SELECT e.employee_id, e.first_name, e.last_name, email,

               (SELECT location_id

                  FROM department d

                 WHERE d.department_id = e.department_id) AS location_id

          FROM employee e

         WHERE e.job_id = 'IT_PROG') a

 WHERE a.location_id > 0;


위의 SQL Location 스칼라 서브쿼리로 구현하였다. 하지만 스칼라 서브쿼리를 Select 하는데는 사용하지 않고 Where 조건으로 사용하는 것을 주목하라.

----------------------------------------------------------------------------------

| Id  | Operation                    | Name        | E-Rows |E-Bytes| Cost (%CPU)|

----------------------------------------------------------------------------------

|*  1 |  FILTER                      |             |        |       |            |

|   2 |   TABLE ACCESS BY INDEX ROWID| EMPLOYEE    |      5 |   195 |     2   (0)|

|*  3 |    INDEX RANGE SCAN          | EMP_JOB_IX  |      5 |       |     1   (0)|

|   4 |   TABLE ACCESS BY INDEX ROWID| DEPARTMENT  |      1 |     7 |     1   (0)|

|*  5 |    INDEX UNIQUE SCAN         | DEPT_ID_PK1 |      1 |       |     0   (0)|

----------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - filter(>0)

   3 - access("E"."JOB_ID"='IT_PROG')

   5 - access("D"."DEPARTMENT_ID"=:B1)

 

위의 Plan 보면 본능적으로 스칼라 서브쿼리가 서브쿼리로 바뀐 것을 알수 있어야 한다. 다시말하면 옵티마이져가 SQL 아래처럼 바꾼 이다.

 

SELECT e.employee_id, e.first_name, e.last_name, email

  FROM employee e

 WHERE e.job_id = 'IT_PROG'

   AND (SELECT location_id

          FROM department d

         WHERE d.department_id = e.department_id) > 0 ;

 

----------------------------------------------------------------------------------

| Id  | Operation                    | Name        | E-Rows |E-Bytes| Cost (%CPU)|

----------------------------------------------------------------------------------

|*  1 |  FILTER                      |             |        |       |            |

|   2 |   TABLE ACCESS BY INDEX ROWID| EMPLOYEE    |      5 |   195 |     2   (0)|

|*  3 |    INDEX RANGE SCAN          | EMP_JOB_IX  |      5 |       |     1   (0)|

|   4 |   TABLE ACCESS BY INDEX ROWID| DEPARTMENT  |      1 |     7 |     1   (0)|

|*  5 |    INDEX UNIQUE SCAN         | DEPT_ID_PK1 |      1 |       |     0   (0)|

----------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - filter(>0)

   3 - access("E"."JOB_ID"='IT_PROG')

   5 - access("D"."DEPARTMENT_ID"=:B1)

 

실행계획과 Predicate Information 완전히 같음을 알수 있다. 이제 10053 Trace 분석해보자.

***************************

Order-by elimination (OBYE)

***************************

중간생략

CVM:   Merging SPJ view SEL$2 (#0) into SEL$1 (#0)

Registered qb: SEL$F5BB74E1 0xc4643d0 (VIEW MERGE SEL$1; SEL$2)

---------------------

QUERY BLOCK SIGNATURE

---------------------

  signature (): qb_name=SEL$F5BB74E1 nbfros=1 flg=0

    fro(0): flg=0 objn=70296 hint_alias="E"@"SEL$2"

 

View Merging 발생하여 SEL$2(인라인뷰 a) SEL$1(메인쿼리) 통합 되어 버렸다. View Merging 발생하여 새로운 쿼리블럭인 SEL$F5BB74E1 생성 되었다. 하지만 쿼리블럭 SEL$F5BB74E1 From 절을 보면 employee(Alias 로는 E) 존재하고 department(D) 존재 하지 않는다. 그렇다면 스칼라 서브쿼리는 어디로 갔을까? 해답은 FPD(Filter Push Down) 기능에 있다.

 

**************************

Predicate Move-Around (PM)

**************************

중간생략

query block SEL$F5BB74E1 (#0) unchanged

FPD: Considering simple filter push in query block SEL$F5BB74E1 (#0)

 (SELECT "D"."LOCATION_ID" FROM "DEPARTMENT" "D")>0 AND "SYS_ALIAS_1"."JOB_ID"='IT_PROG'

FPD: Considering simple filter push in query block SEL$3 (#0)

"D"."DEPARTMENT_ID"=:B1

try to generate transitive predicate from check constraints for query block SEL$3 (#0)

finally: "D"."DEPARTMENT_ID"=:B1


FPD
기능에 의해서 위에서 새로 생성된 쿼리블럭 SEL$F5BB74E1 조건절에 서브쿼리를 생성하고 있다. 또한 새로 생성된 서브쿼리에 "D"."DEPARTMENT_ID"=:B1 조건을 밀어넣고 있다.

 

검증

스칼라  서브쿼리가 서브쿼리로 바뀌었으므로 서브쿼리에 사용할수 있는 힌트 Push_subq 사용해보자. 이것이 가능해야지만 진정한 서브쿼리이다.

 

SELECT /*+ PUSH_SUBQ(@SUB) */

        a.employee_id, a.first_name, a.last_name, a.email

  FROM (SELECT e.employee_id, e.first_name, e.last_name, email,

               (SELECT /*+ QB_NAME(SUB) */ location_id

                  FROM department d

                 WHERE d.department_id = e.department_id) AS location_id

          FROM employee e

         WHERE e.job_id = 'IT_PROG') a

 WHERE a.location_id > 0;

 

----------------------------------------------------------------------------------

| Id  | Operation                    | Name        | E-Rows |E-Bytes| Cost (%CPU)|

----------------------------------------------------------------------------------

|*  1 |  TABLE ACCESS BY INDEX ROWID | EMPLOYEE    |      1 |    39 |     2   (0)|

|*  2 |   INDEX RANGE SCAN           | EMP_JOB_IX  |      5 |       |     1   (0)|

|   3 |   TABLE ACCESS BY INDEX ROWID| DEPARTMENT  |      1 |     7 |     1   (0)|

|*  4 |    INDEX UNIQUE SCAN         | DEPT_ID_PK1 |      1 |       |     0   (0)|

----------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - filter(>0)

   2 - access("E"."JOB_ID"='IT_PROG')

   4 - access("D"."DEPARTMENT_ID"=:B1)

 

실행계획을 보면 알겠지만 Subquery Pushing 이 발생하여 Id 기준으로 2번과 3번이 동일 Level 상에 존재한다. Subquery Pushing 이 성공적으로 수행된것을 알수 있다.

 

한단계 나아가 보자

CREATE INDEX HR.EMP_JOB_DEPT_IX ON HR.EMPLOYEE (JOB_ID, DEPARTMENT_ID);

 

EMPLOYEE 테이블에 JOB_ID, DEPARTMENT_ID 생성 하였다. 바로 위에서 실행한 SQL 다시 실행 해보자.

--> 여기서 PUSH_SUBQ 를 적용한 SQL 실행한다.

 

---------------------------------------------------------------------------------------

| Id  | Operation                     | Name            | E-Rows |E-Bytes| Cost (%CPU)|

---------------------------------------------------------------------------------------

|   1 |  TABLE ACCESS BY INDEX ROWID  | EMPLOYEE        |      1 |    39 |     2   (0)|

|*  2 |   INDEX RANGE SCAN            | EMP_JOB_DEPT_IX |      1 |       |     1   (0)|

|   3 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENT      |      1 |     7 |     1   (0)|

|*  4 |     INDEX UNIQUE SCAN         | DEPT_ID_PK1     |      1 |       |     0   (0)|

---------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("E"."JOB_ID"='IT_PROG')

       filter(>0)

   4 - access("D"."DEPARTMENT_ID"=:B1)

  

이것은 제공자 서브쿼리가 아니다

실행계획은 마치 제공자 서브쿼리처럼 바뀌었지만 이것은 제공자 서브쿼리가 아니고 Subquery Pushing 에 의한 효과이다. Predicate Information 을 주목하라. ID 기준으로 2번에서 Filter 가 수행된다. . (JOB_ID, DEPARTMENT_ID) 인덱스를 사용하지 않은 SQLPredicate Information을 보면 EMPLOYEE 테이블 엑세스 시에 filter 가 발생함을 알수 있다. 이것이 바로 Subquery Pushing 과 인덱스에 의한 Early Filter 의 효과이다. 물론 Early Filter 의 개념은 조인순서상에 서브쿼리를 최대한 먼저 조인 하는것으로 바꾸는 것이다. 하지만 위와 같은 Early Filter의 부가적인 기능도 있음을 알아야 한다.

 Subquery Pushing 에 의한 Early Filter 기능은 Using Sub query Method( Filter / Access sub Query ) 글을 참조하라

결론:
이처럼
Oracle Query Transformer
스칼라 서브쿼리를 Filter 조건으로 사용할 SSTS를 발생시킨다.. 여러분이 Query Transformation 의도 하던 의도하지 않던 말이다.

PS :
제목이 이상하다는 의견이 있다. 제목은 옵티마이져가  변환을 수행한다는 의미이다. 수동으로 스칼라 서브쿼리를 서브쿼리로 고치라는 의미가 아니므로 착오가 없길 바란다.


신고
Posted by extremedb

댓글을 달아 주세요

  1. 궁금이 2009.09.10 17:20 신고  댓글주소  수정/삭제  댓글쓰기

    스칼라 서브쿼리는 Outer join을 사용하는 대신 사용하기도 합니다.
    이 경우 서브쿼리로 바뀌게 되면 결과 건수가 달라지지는 않나요..?
    그러니까 스칼라 서브쿼리의 값이 null이 되는 경우가 있다고 가정할 때 말입니다.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.10 17:44 신고  댓글주소  수정/삭제

      스칼라 서브쿼리의 결과가 null 이라고 해도 결과건수가 달라지지 않습니다.
      예를 들어 보겟습니다.
      스칼라 값이 null 일경우:
      a.location_id > 0 이렇게 되면 null 인값은 당연히 빠져야 하겠죠. 우리가 상수나 변수 조건을 줄때는 null 은 빠지고 나옵니다.
      만약 a.location_id > 0 인 데이터 + location_id 값이 null 인 데이터를 보고자 하시면
      a.location_id > 0 or a.location_id is null 로 하시면 됩니다.

  2. Favicon of http://performeister.tistory.com BlogIcon novathinker 2009.09.10 18:13 신고  댓글주소  수정/삭제  댓글쓰기

    그건 의도적으로 SQL을 변경한 것이구요.
    이것 처럼 Oracle이 최적화 과정에서 ReWrite하는 경우 결과 셋이 달라질 수 있는지를 물어본 것입니다.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.10 18:18 신고  댓글주소  수정/삭제

      제가 말씀드린것처럼 SSTS( Scalar Subquery To Subquery ) 기능은 where 절에 스칼라 서브쿼리의 조건을 준 경우에만 발생하므로 결과가 달라지지 않습니다.
      이것을 질문한것이 아니라면 결과가 달라질것으로 의심되는 SQL 을 주시기 바랍니다.

  3. feelie 2009.09.10 18:33 신고  댓글주소  수정/삭제  댓글쓰기

    새로운 내용을 볼때마다 머리가 띵합니다.
    아마도 아직 정확한 지식부족이라는 생각이 듭니다.
    내용 잘보고, 앞으로도 계속 잘 보겠습니다.

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.10 18:54 신고  댓글주소  수정/삭제

      여기에 올려지는 모든 글들은 어느정도 난위도가 있는것들 입니다. 머리가 아프시더라도 실망 하지 마시고 꾸준히 보신다면 분명히 성과가 있을것입니다.

  4. Favicon of http://blog.naver.com/xsoft BlogIcon 강정식 2009.09.11 10:38 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 동규님. 오랜만에 글을 남겨봅니다 ^^

    이번에도 재미난 포스팅을 올려주셔서 재밌게 보았습니다.
    저도 실제로 튜닝을 할 때 복잡한 SQL에서 스칼라 서브쿼리가 실행계획에서 변경되었을 때 순간적으로 해석하기가 힘든 경우가 있더라구요.

    이번 내용처럼 스칼라 서브쿼리임에도 서브쿼리로 변형이 된다던가, 또는 스칼라 서브쿼리가 Hidden되어 보이지 않는다던가 말이죠.

    특히나 View 안에서 GROUP BY를 사용하면서 스칼라 서브쿼리를 사용할 때 뷰 밖에서 조건을 주고 실행계획을 볼 경우 스칼라 서브쿼리가 안보여서 인위적으로 해체(?)의 수순을 밟기도 합니다.

    제가 참여하는 스터디에서 간단하게 테스트 한 내용입니다.

    http://wiki.oracleclub.com/pages/viewpage.action?pageId=3899396#9.%EC%BF%BC%EB%A6%AC%EB%B3%80%ED%99%98-2.%EC%8A%A4%EC%B9%BC%EB%9D%BC%EC%84%9C%EB%B8%8C%EC%BF%BC%EB%A6%AC

    항상 좋은 글 올려주셔서 감사하게 생각하고 있습니다.

    ps. 저는 블로그에 포스팅을 못한지 근 3개월째 되가고 있어서 거의 방문자가 없는데 동규님은 컨설팅 업무도 하시면서 이렇게 포스팅도 꾸준히 하시는것을 보고 그 열정에 매번 감탄을 하고 있습니다. 저도 빨리 좋은 내용을 가지고 찾아뵙도록 하겠습니다. 오늘 하루도 행복하세요

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.11 11:01 신고  댓글주소  수정/삭제

      오랜만 입니다.
      테스트 내용을 잘보았습니다.
      좋은 정보 감사드립니다.
      상당한 수준의 책을 스터디 하셨네요.
      분명히 성과가 있을것입니다.
      좋은 하루되세요

  5. Favicon of http://ukja.tistory.com BlogIcon 욱짜 2009.12.15 11:04 신고  댓글주소  수정/삭제  댓글쓰기

    Query Transformation을 이해하지 못하면 옵티마이저를 이해할 수 없다는게 제 철학중 하나인데, 그걸 실제로 잘 설명해주시고 계십니다. ^^

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.12.15 15:40 신고  댓글주소  수정/삭제

      저도 같은 생각을 가지고 있습니다. 현장에서 고급 DBA들이 풀지못하는 많은 문제들이 Query Transformation 과 관련된 문제였습니다.
      감사합니다.

  6. Favicon of http://1ststreet.tistory.com BlogIcon SITD 2012.03.13 15:21 신고  댓글주소  수정/삭제  댓글쓰기

    마지막 실행계획 만봤을 땐
    4 - access("D"."DEPARTMENT_ID"=:B1)
    가 가장 먼저 풀리는 것 처럼 보이는데,

    실제론
    2 - access("E"."JOB_ID"='IT_PROG')
    filter(>0)
    의 필터가 수행될 때 E의 부서아이디가 4에 상수로 삽입되는거 같은데 맞나요?

    실행계획은 위에서 아래로, 오른쪽에서 왼쪽으로 봐야 한다고 배웠는데, 그게 안통하는 경우가 간혹 있는거 같네요.

    좋은 지식 나눠주셔서 감사합니다 ^^

오랜만에 책장 정리를 하였다.
그러다가 책장의 한칸에 필독 List 를 만들었다.
나의 경우 필독 List 란 한번 보았지만 반드시 두번이상 다시 보아야 할 List 와 꼭 보아야 하지만 아직 보지 못한것들을 정리한 것 이다.

사용자 삽입 이미지

언제 이것들을 다 보려나?
보면 알겠지만 오른쪽은 모델링 혹은 Architecture 중간은 오라클 왼쪽은 일할때 도움을 주는 도서 가장 왼쪽은 재미있는 것들  순으로 나열해 보았다.

재즈 속으로 : 이 책은 15년전에 구입한 것 이지만 다시 한번 보려 한다.
                    여기서 듀크 앨링턴 부터 허비행콕 까지의 여행을 할수 있었다.

로지컬 씽킹 : 제목이 이상하지만  논리적인 생각과 글쓰기의 기법을 알려주는 책이다.
                    바바라 민토의 논리의 기술과 내용이 같으므로 둘중에 하나만 보면 된다.

The CRM Hand Book : CRM 프로젝트를 하는사람들에겐 필독서라 할수 있다.
                                     IT 관점에서 바라보는 CRM 도서.
                                     모델링시 도움을 많이 받았다.

Oracle Performace Firefighting : 스티브 아담스의 책 Oracle8i Internal Services for Waits, Latches, Locks,
                                                    and Memory 의 Upgrade 버젼 이라고 보면 된다.
                                                    저자는 Craig Shallahamer 라는 사람인데 Cary Millsap 과는 친구 사이이다.
                                                    열공중....

DW 2.0 : 2.0 의 시대이다. DBA 2.0, WEB 2.0, 오라클 11g 2.0 ....
              이책은 DW 모델링 책이 아니라 Architecture 책이다. 아지 보지 못했다.

Physical Database Design : 몇 안되는 물리 모델링 책이다. 아쉬운 점은 IBM DB2 의 관점이 많다는 것.

Data Model Patterns 시리즈 : 자바에만 Pattern 책이 있는건 아니다. 모델링 도 많이 있다.
                                               바커의 Case Method 를 더욱 빛나게 한 시리즈 이다.
                                               국내에 제대로 된 모델 Pattern 책이 한권 이라도 있으면 좋으련만...
                                               언제쯤 Pattern 책이 나오려나?

편집후기 : 혹시 여러분이 정리한 필독 리스트가 있으면 공유 해주기 바란다.

신고
Posted by extremedb

댓글을 달아 주세요

  1. Favicon of http://energ.tistory.com BlogIcon 에너자이죠 2009.09.04 09:21 신고  댓글주소  수정/삭제  댓글쓰기

    오라클 쪽 책들은 한번 구해서 읽어봐야 겠네요.
    모델링은 아직.. ㅎㅎ

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.04 09:34 신고  댓글주소  수정/삭제

      반갑습니다.
      Forecasting Oracle performance 는 튜닝 책이 아닙니다. 이것은 미래의 성능을 예측하는 능력을 기르는 책이므로 주의 하셔야 합니다.

  2. 혈기린 2009.09.04 10:08 신고  댓글주소  수정/삭제  댓글쓰기

    모델링 관련책보고싶네요 얼릉 원서의 벽을 무너뜨려야 하는데 ㅎㅎ
    이제 번역서는 나오지 않나 봅니다 ㅜ.ㅜ

  3. Favicon of http://hongman111.tistory.com BlogIcon 홍E 2009.09.07 13:56 신고  댓글주소  수정/삭제  댓글쓰기

    저는 나의라임오렌지나무 두번읽었어요 ^^ 그런데 사진에는 있고 목록에는 없네요 ㅠ.ㅠ 읽으신 거겠죠?? ㅎㅎ 위 목록과는 전혀 다른책이지만 '네 안에 잠든 거인을 깨워라' <--요책 읽을만 하더군요. 자기개발에 대한 책중에서는 최고인듯 싶어요..

    • Favicon of http://scidb.tistory.com BlogIcon extremedb 2009.09.07 14:05 신고  댓글주소  수정/삭제

      네 나의 라임 오렌지 나무는 한번 읽었는데 한번 더 보려 합니다.
      '네 안에 잠든 거인을 깨워라' 그런 책이 있었네요. 반드시 읽도록 하겠습니다.

  4. 나그네 2009.09.09 13:13 신고  댓글주소  수정/삭제  댓글쓰기

    Physical Database Design 이 책이 참 흥미롭네요. DB2관점이라니 DB2쪽은 너무 외면 받는거 같아 아쉬웠는데 좋은 소식입니다.

  5. Favicon of http://lemonfish.egloos.com BlogIcon killy 2009.10.29 23:52 신고  댓글주소  수정/삭제  댓글쓰기

    Date on Database 는 데이터베이스에서 날짜 타입을 어떻게 다루나? 에 관한 2000~2006 년까지의 변천사를 심도있게 다루는 책인줄 알았습니다. 아마존에서 보니 저자이름에 Date 가 있더군요. Joel on Software 같은 삘로 제목을 지은 거군요. 하하핫... 근데... 가격의 압박! 아... 이러니까 더 보고싶네요.