메뉴 건너뛰기

tnt_db

Oracle TUNING-01

운영자 2002.09.18 13:03 조회 수 : 2739 추천:23

TABLE :

  CREATE TABLE SALE (SALE_DATE VARCHAR2(08) NOT NULL,
                      SALE_SEQ  NUMBER(05)   NOT NULL,
                      CUST_CODE VARCHAR2(06) NOT NULL,
                      ITEM_CODE VARCHAR2(10) NOT NULL,
                      CONSTRAINTS XPKSALE  PRIMARY KEY (SALE_DATE,SALE_SEQ));
   CREATE INDEX XIE1SALE ON  SALE(CUST_CODE,SALE_DATE);
   --
   CREATE TABLE ITEM (ITEM_CODE VARCHAR2(10) NOT NULL,
                      ITEM_NAME VARCHAR2(40),
                      CONSTRAINTS X_PKITEM PRIMARY KEY (ITEM_CODE) );
   --
   CREATE TABLE CUST (CUST_CODE VARCHAR2(06) NOT NULL,
                      CUST_NAME VARCHAR2(40),
                      CONSTRAINTS X_PKCUST PRIMARY KEY (CUST_CODE));

   --

DATA :

   SELECT * FROM SALE WHERE  SALE_DATE BETWEEN '19990601' AND '19990630'
   19990601 1 111120 A3MCT
   19990602 2 111120 A3MCT
   19990603 3 111120 A3MCT
   19990604 4 111120 A3MCT
   19990605 5 111120 A3MCT
   19990606 1 111112 AAAC
   19990615 1 111112 A3MCT
   19990630 2 111112 AAAM-D

   SELECT * FROM CUST WHERE  CUST_CODE BETWEEN '111111' AND '222222'
   111111 test1111111
   111112 test111112
   111120 test111120
   111123 test1111123
   111124 test111124
   111131 test1111131
   111132 test111132
   111140 test111140
   111143 test1111143
   111144 test111144
   111151 test1111151
   111152 test111152
   111160 test111160
   111163 test1111163
   111164 test111164
   111171 test1111171
   111172 test111172
   111180 test111180
   111183 test1111183
   111184 test111184
   111191 test1111191
   111192 test111192

   SELECT * FROM ITEM WHERE  ITEM_CODE LIKE 'A%'

   A3MA 트리메칠아민
   A3MCT 3-메캅토 프로피오니 산
   AAAC 아크릴산
   AAAM 아크릴아마이드
   AAAM-D 아크릴아마이드
   AABN 아조비스이소부칠롤니트릴
   AACTN 아세톤
   AACTNIM 아세톤
   AADPA 아디픽산
   AALRE 알키드 수지
   AAMBF 불화암모
   AAMCL 암모클로라이드
   AANM 에이엔 모노마
   AANON 싸이크로헥사논
   AAPS 과류산암모늄
   AAPST 아크릴프라스틱씨트
   AASFX 합성수지아소픽스F40

참고 :위와 같은 테이블과 DATA 가 있고,테이블에서도 알 수 있듯이
      SALE에는 아래와 같은 두종류의 INDEX 가 존재하고,
      ITEM과 CUST에는 PRIMARY KEY 만이 존재합니다.
--
      SELECT TABLE_NAME,INDEX_NAME,COLUMN_NAME
      FROM   USER_IND_COLUMNS
      WHERE  TABLE_NAME = 'SALE'
--
      TABLE_NAME  INDEX_NAME  COLUMN_NAME
      ----------- ----------- ------------
      SALE        X_PKSALE    SALE_DATE
      SALE        X_PKSALE    SALE_SEQ
      SALE        X_IE1SALE   CUST_CODE
      SALE        X_IE1SALE   SALE_DATE

문제 : ORDER BY 를 사용하지 않고 순수하게 INDEX SCAN을 이용하여
       DATA를 CUST_CODE,ITEM_CODE 순서로 보기를 원합니다.
       불가능하다고 생각했습니다.
       우선 ITEM과 CUST의 연결고리가 SALE 이기때문에 무조건 기준은
       SALE 이 되어야 한다고 생각했습니다.
       그 상태에서 CUST_CODE,ITEM_CODE 순서로
       DATA를 읽어오기 위해서는
       SALE에 CUST_CODE,ITEM_CODE 로 만들어진 INDEX가
       존재해야 하는데 그렇지 않습니다.
       먼저,
       SALE을  A,CUST를 B,ITEM을 C 로 각각 ALIAS를 부여했을때
       조건은 다음과 같습니다.

      WHERE  A.SALE_DATE BETWEEN '19990601' AND '19990630'
       AND    B.CUST_CODE BETWEEN '111111' AND '222222'
       AND    C.ITEM_CODE LIKE 'A%'
       AND    B.CUST_CODE = A.CUST_CODE
       AND    C.ITEM_CODE = A.ITEM_CODE

정보 : 먼저 이해할것은 OPTIMZER가 DRIVING TABLE을 선택하는 기준을
       BETWEEN과 LIKE 가 같다고 여기는듯 합니다.
       그리고 RULE-BASED MODE에서 우선순위가 같은 INDEX가 주어지면
       우선적으로 뒤에 기술된 테이블을 드라이빙 테이블로 봅니다.
       이부분은 TUNING 책에 나오는 내용입니다.
       따라서 위의 조건에서 보듯이 3개의 테이블이 OPTIMIZER의
       우선순위 선택에 영향을 주지 못합니다.
       그로 인해 FROM절의 기술된 순서의 뒤에서부터 DRIVING 테이블로
       읽혀들어갑니다.

의문 : 다만 SALE/CUST 로 조인이 된 후에 ITEM과 JOIN이 되든지,
       SALE/ITEM으로 조인이 된 후에 CUST로 조인이 되는것이 정상이라고
       생각했습니다.
       ITEM과 CUST는 서로 조인이 일어날 기준이 없기 때문입니다.
          
해결 :    
      경우1: SALE CUST ITEM 순의 조인
          SELECT A.SALE_DATE,A.SALE_SEQ,
                 A.CUST_CODE,
                 B .CUST_NAME,
                C. ITEM_CODE,
                 C.ITEM_NAME
          FROM   ITEM C ,CUST B,SALE A
          WHERE  A.SALE_DATE BETWEEN '19990601' AND '19990630'
          AND    B.CUST_CODE BETWEEN '111111' AND '222222'
          AND    C.ITEM_CODE LIKE 'A%'
          AND    B.CUST_CODE = A.CUST_CODE
          AND    C.ITEM_CODE = A.ITEM_CODE

          PLAN : SALE CUST ITEM 순서대로 조인이 이루어졌습니다.
                SELECT STATEMENT Optimizer=CHOOSE
                  NESTED LOOPS
                    NESTED LOOPS
                      TABLE ACCESS (BY INDEX ROWID) OF SALE
                        INDEX (RANGE SCAN) OF X_PKSALE (UNIQUE)
                      TABLE ACCESS (BY INDEX ROWID) OF CUST
                        INDEX (UNIQUE SCAN) OF X_PKCUST (UNIQUE)
                    TABLE ACCESS (BY INDEX ROWID) OF ITEM
                      INDEX (UNIQUE SCAN) OF X_PKITEM (UNIQUE)
           OUTPUT : 결과는 물론SALE_DATE,SALE_SEQ 순서입니다.
                   SALE_DAT SALE_SEQ  CUST_C CUST_NAME    ITEM_CODE  ITEM_NAME
                   -------- --------- ------ ------------ ---------- ------------------------
                   19990601         1 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                   19990602         2 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                   19990603         3 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                   19990604         4 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                   19990605         5 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                   19990606         1 111112 test111112   AAAC       아크릴산
                   19990615         1 111112 test111112   A3MCT      3-메캅토 프로피오니 산
                   19990630         2 111112 test111112   AAAM-D     아크릴아마이드

      경우2: CUST SALE ITEM 순의 조인
          SELECT A.SALE_DATE,A.SALE_SEQ,
                 A.CUST_CODE,
                 B .CUST_NAME,
                 C.ITEM_CODE,
                 C.ITEM_NAME
          FROM   ITEM C, SALE A,CUST B
          WHERE  A.SALE_DATE BETWEEN '19990601' AND '19990630'
          AND    B.CUST_CODE BETWEEN '111111' AND '222222'
          AND    C.ITEM_CODE LIKE 'A%'
          AND    B. CUST_CODE = A.CUST_CODE
          AND    C. ITEM_CODE = A.ITEM_CODE

          PLAN : CUST SALE ITEM 순서대로 조인이 이루어졌습니다.
                SELECT STATEMENT Optimizer=CHOOSE
                  NESTED LOOPS
                    NESTED LOOPS
                      TABLE ACCESS (BY INDEX ROWID) OF CUST
                        INDEX (RANGE SCAN) OF X_PKCUST (UNIQUE)
                      TABLE ACCESS (BY INDEX ROWID) OF SALE
                        INDEX (RANGE SCAN) OF X_IE1SALE (NON-UNIQUE)
                    TABLE ACCESS (BY INDEX ROWID) OF ITEM
                      INDEX (UNIQUE SCAN) OF X_PKITEM (UNIQUE)

           OUTPUT : 결과는 물론 CUST_CODE,SALE_DATE 순서입니다.
                    SALE_SEQ와는 순서가 무관합니다.
                    SALE 의 PRIMARY KEY가 이용된것이 아니라 CUST_CODE,SALE_DATE INDEX가
                    이용 되었기 때문입니다.

                  SALE_DAT SALE_SEQ  CUST_C CUST_NAME    ITEM_CODE  ITEM_NAME
                  -------- --------- ------ ------------ ---------- -----------------------
                  19990606         1 111112 test111112   AAAC       아크릴산
                  19990615         1 111112 test111112   A3MCT      3-메캅토 프로피오니 산
                  19990630         2 111112 test111112   AAAM-D     아크릴아마이드
                  19990601         1 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                  19990602         2 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                  19990603         3 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                  19990604         4 111120 test111120   A3MCT      3-메캅토 프로피오니 산
                  19990605         5 111120 test111120   A3MCT      3-메캅토 프로피오니 산

      경우3: CUST ITEM SALE 순의 조인
           SELECT A.SALE_DATE,A.SALE_SEQ,
                  A.CUST_CODE,
                  B.CUST_NAME,
                  C.ITEM_CODE,
                 C.ITEM_NAME
           FROM   SALE A,ITEM C,CUST B
           WHERE  A.SALE_DATE BETWEEN '19990601' AND '19990630'
           AND    B. CUST_CODE BETWEEN '111111' AND '222222'
           AND     C.ITEM_CODE LIKE 'A%'
           AND    B.CUST_CODE = A.CUST_CODE
           AND    C.ITEM_CODE = A.ITEM_CODE
      
           PLAN : 전혀 관계가 없는 CUST와 ITEM의 조인이 먼저 이루어졌습니다.
                  따라서 순서는 애초 원하던 CUST_CODE,ITEM_CODE 순서가 되었습니다.
                 SELECT STATEMENT Optimizer=CHOOSE
                   NESTED LOOPS
                     NESTED LOOPS
                       TABLE ACCESS (BY INDEX ROWID) OF CUST
                         INDEX (RANGE SCAN) OF X_PKCUST (UNIQUE)
                       TABLE ACCESS (BY INDEX ROWID) OF ITEM
                         INDEX (RANGE SCAN) OF X_PKITEM (UNIQUE)
                     TABLE ACCESS (BY INDEX ROWID) OF SALE
                       INDEX (RANGE SCAN) OF X_IE1SALE (NON-UNIQUE)
      
           OUTPUT :CUST_CODE,ITEM_CODE 순서입니다.
                   19990615  1 111112 test111112 A3MCT 3-메캅토 프로피오니 산
                   19990606  1 111112 test111112 AAAC 아크릴산
                   19990630  2 111112 test111112 AAAM-D 아크릴아마이드
                   19990601  1 111120 test111120 A3MCT 3-메캅토 프로피오니 산
                   19990602  2 111120 test111120 A3MCT 3-메캅토 프로피오니 산
                   19990603  3 111120 test111120 A3MCT 3-메캅토 프로피오니 산
                   19990604  4 111120 test111120 A3MCT 3-메캅토 프로피오니 산
                   19990605  5 111120 test111120 A3MCT 3-메캅토 프로피오니 산            
           비록 조건절이 주어져서 CUST 와 ITEM 두테이블 모두 INDEX SCAN이 일어났지만
           조건에 맞는 DATA 끼리 CARTESIAN PRODUCT이 형성되지 않았나 싶습니다.
           그래서 TEST로 만들었던 DATA가 적은 TABLE 대신 실데이타가 들어있는
           실제 테이블을 이용 했더니 PLAN은 같은데,RESPONSE TIME에 엄청난 차이가
           있었습니다.
           결론은 SALE TABLE에 CUST_CODE,ITEM_CODE순의 INDEX를 만들던지,
           차라리 최종 결과 ROW가 많지 않으면 ORDER BY를 쓰는것이 났다는 것입니다.
           아직 풀리지 않는 의문이 있다면
           서로간의 조인관계를 설정해주지않은 CUST와 ITEM이 먼저 JOIN이 일어난다는 것인데
           이부분에 대한 명확한 설명을 해주실수 있는 분이라면
           저에게 메일을 주셨으면 합니다.
           CARTESIAN PRODUCT역시 JOIN 이기때문에 그렇다고 한다면,
           EQUAL JOIN,NON-EQUAL JOIN간에도 JOIN의 우선순위가 없나요??.
           우선순위가 있는걸로 알고 있었는데??.
           만약 두개사이에 우선순위가 있다면 CARTESIAN PRODUCT 은 우선순위가
           앞의 둘보다 나중일듯 한데!...
           좀더 고민을 한 후 답을 올리겠습니다.

번호 제목 글쓴이 날짜 조회 수
46 빠진이빨찾기 II 운영자 2002.09.18 3067
45 빠진이빨찾기 운영자 2002.09.18 3122
44 순환참조에서의 상위코드로집계 운영자 2002.09.18 3226
43 CONNECT BY의 SORT와 JOIN 운영자 2002.09.18 2811
42 REPORT 양식맞추기4 운영자 2002.09.18 2597
41 REPORT 양식 맞추기 III 운영자 2002.09.18 3015
40 REPORT 양식 맞추기 II 운영자 2002.09.18 2646
39 REPORT 양식 맞추기 운영자 2002.09.18 31359
38 1:1 JOIN / 1:M JOIN 운영자 2002.09.18 3000
» TUNING-01 운영자 2002.09.18 2739
36 소계와 합계 운영자 2002.09.18 3489
35 중복DATA 찾아내기 운영자 2002.09.17 2817
34 GROUP별 DATA 분류 운영자 2002.09.17 2982
33 PARAMETER값에 따라 변경이 일어나는 문장 운영자 2002.09.17 15808
32 SELF JOIN 운영자 2002.09.17 3408
31 Outer Join 운영자 2002.09.17 2918
30 HINTS (출처-Oracle8.0 Tuning Guide) 운영자 2002.09.17 2735
29 단일행 문자 함수 운영자 2002.09.17 2977
28 단일행 수치 함수 운영자 2002.09.17 2869
27 NOT IN 의 함정 운영자 2002.09.17 2713
위로