index를 태우고 싶은데요. 0 2 995

by 정규직 [SQL Query] [2014.09.15 12:05:22]


아래와 같은 테이블 구조를 가지고 있는데요.

 사업장       사업유형    날짜  번호
---------------------------------------------------------------
   가       수익  2014.01.01  1
   가       수익  2014.01.05  2
   가       수익  2014.01.07  3
   나       수익  2014.01.03  4
   나       수익  2014.01.05  5
   가       수익  2014.01.09  6
   다       비수익 2014.01.15  7
   ...
----------------------------------------------------------------
INDEX는 (사업장 + 사업유형 + 날짜) 로 구성되어 있습니다.

데이터 조회 시 사업장과 사업유형을 여러개로 선택해야 해서
강좌에 올라온 Pipelined Table Function 내용을 참조로 해서
(http://www.gurubee.net/lecture/2238)
문자열을 넘기면 TABLE 형태로 넘겨 받게 처리 했습니다.

여기서 문제가 발생했는데요.
index가 있음에도 불구하고 index range scan를 하지 못하고
full table scan을 하거나 index skip scan를 하는 현상이 발생되고 있습니다.

SQL)
SELECT 사업장, 사업유형, 날짜
  FROM TABLE
 WHERE 사업장 IN (SELECT * FROM TABLE(pipe_table_func('가,나,다')))
    AND 사업유형 IN (SELECT * FROM TABLE(pipe_table_func('수익,비수익')))
    AND 날짜 BETWEEN '20140101' AND '20140131'

-----------------------------------------------------------------------------
| Id  | Operation                           | Name                |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                       |
|*  1 |  FILTER                              |                      |
|   2 |   TABLE ACCESS BY INDEX ROWID       | TABLE  |
|*  3 |    INDEX SKIP SCAN                  | INDEX1  |
|   4 |   COLLECTION ITERATOR PICKLER FETCH | pipe_table_func |
|   5 |   COLLECTION ITERATOR PICKLER FETCH | pipe_table_func |

해결방법이 없을까요 ?


 

by 마농 [2014.09.15 13:23:57]

1. 각 조건이 각개전투하는 모양새입니다.
  - 조건들이 서로 팀을 이루어야 할 듯 합니다.
2. 함수사용에 대한 부담도 있습니다.
  - 함수 사용 안해도 될 듯 합니다.

WITH t AS
(
SELECT 사업장, 사업유형, 날짜
  FROM (SELECT REGEXP_SUBSTR(v, '[^,]+', 1, LEVEL) 사업장
          FROM (SELECT '가,나,다' v FROM dual)
         CONNECT BY LEVEL <= LENGTH(v) - LENGTH(REPLACE(v, ',')) + 1
        )
     , (SELECT REGEXP_SUBSTR(v, '[^,]+', 1, LEVEL) 사업유형
          FROM (SELECT '수익,비수익' v FROM dual)
         CONNECT BY LEVEL <= LENGTH(v) - LENGTH(REPLACE(v, ',')) + 1
        )
     , (SELECT TO_CHAR(TO_DATE(s, 'yyyymmdd') + LEVEL - 1, 'yyyymmdd') 날짜
          FROM (SELECT '20140101' s, '20140131' e FROM dual)
         CONNECT BY LEVEL <= TO_DATE(e, 'yyyymmdd') - TO_DATE(s, 'yyyymmdd') + 1
        )
)
SELECT b.*
  FROM t a
     , table b
 WHERE a.사업장 = b.사업장
   AND a.사업유형 = b.사업유형
   AND a.날짜 = b.날짜
;

 


by 정규직 [2014.09.15 13:49:28]

감사합니다. 많은 도움 되었습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입