조건절 || '' 유무에 따라 인덱스 타는 실행계획이 다릅니다ㅠ 0 4 2,546

by aram [SQL Query] 인덱스 [2015.01.12 17:00:45]


질문 :

아래 쿼리A 와 쿼리B의 차이점은 YYYYMM_INV 컬럼 조건절에서 ||'' 가 붙느냐 안붙느냐 뿐인데

그로인해 실행계획이 달라져버립니다ㅠㅠ

||'' 가 무슨 역할을 하는지 모르겠어요..

검색해도 나오지 않아 질문 드립니다ㅠ

 

 

<쿼리 A>

SELECT *
  FROM IEBL_PROD_USE_AMT
 WHERE YYYYMM_INV || '' = '201501'
   AND ID_ACCT          = '1000458053'
   AND ID_SO            = '2100'
   AND FG_INV           = '01'
   AND CD_RSLT          = '30';

Execution Plan
-----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=208)
   1    0   TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'IEBL_PROD_USE_AMT' (Cost=3 Card=1 Bytes=208)
   2    1     INDEX (RANGE SCAN) OF 'IEBL_PROD_USE_AMT_IDX6' (NON-UNIQUE) (Cost=4 Card=1)
-----------------------------------------------------------

 

<쿼리 B>

SELECT *
  FROM IEBL_PROD_USE_AMT
 WHERE YYYYMM_INV       = '201501'
   AND ID_ACCT          = '1000458053'
   AND ID_SO            = '2100'
   AND FG_INV           = '01'
   AND CD_RSLT          = '30';

Execution Plan
-----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=245 Card=7 Bytes=1K)
   1    0   TABLE ACCESS (FULL) OF 'IEBL_PROD_USE_AMT' (Cost=245 Card=7 Bytes=1K)
-----------------------------------------------------------

 

 

<테이블 정보>

  Table Partition
  -----------------------------------------------------------------------------
  Type = Range Partition
  Keys = ID_SO,YYYYMM_INV

 

<인덱스 정보>

 INDEX
 -----------------------------------------------------------------------------

IEBL_PROD_USE_AMT_IDX6 : ID_ACCT,YYYYMM_INV,FG_INV,ID_SO,AMT_UNPMT

by 아발란체 [2015.01.12 17:18:24]

조건 컬럼을 가공하면 실행 계획이 달라집니다.

보통 성능이 더 나빠집니다.

조건 컬럼이 아니라 조건 값을 가공하는 것을 권장합니다.

근디... 실행 계획이... = ㅁ =)ㅋ ㅎㅎ


by 마농 [2015.01.12 17:37:07]

<쿼리 A>
 - 파티션 키가 가공되어 특정 파티션만을 스캔하지 못하고
 - 글로벌 인덱스인 idx6 를 이용하게 된거구요
<쿼리 B>
 - 파티션 키 조건이 모두 들어와 있어서 특정 파티션만을 스캔한 것입니다.
<결론>
 - idx6 의 정보를 보면 파티션 키인 ID_SO, YYYYMM_INV 를 포함하는데
 - 이 파티션 키 조건이 항상 들어오는 조건이라면?
 - 글로벌이 아닌 로컬인덱스로 생성해야 할듯 합니다.


by aram [2015.01.12 18:10:15]

답변감사합니다.

조건절 좌변을 가공함으로써 파티션을 안 타게 하였고, 그로인해 인덱스(글로벌)를 탔다(쿼리A)

조건절 좌변을 가공 안했기 때문에 바로 파티션을 탔고 그 특정 파티션을 풀로 탔다 (쿼리B)

제가 제대로 이해한 것 맞나요?

그리고 결론에 글로벌이 아닌 로컬인덱스로 생성해야 한다는 조언은 무엇 때문인지요ㅠ?


by 마농 [2015.01.12 18:34:05]

글로벌 인덱스는 파티션 키와는 다른 결합의 인덱스일때 사용하는거구요.
이걸 만들어 놓으면 파티션별 테이블 작업을 하게 될 때
글로벌 인덱스가 언유저블로 빠지게 되어 리빌드를 해줘야만 하는 상황이 발생됩니다.
하지만 로컬인덱스는 해당 파티션에만 영향을 받으므로 리빌드할 필요도 없구요.
파티션 키를 포함하는 인덱스를 굳이 글로벌로 만들어 위험을 자초할 필요가 없구요.


위에서도 글로벌 인덱스를 만들었지만 제대로 타질 않고 파티션풀스캔을 했구요.
이부분은 옵티마이저가 판단미스를 한게 아닐까도 생각이 들구요.
파티션 키에 억지로 가공을 하여 글로벌 인덱스를 타게 했지만.
인덱스의 두번째 항목이 가공되어 인덱스 엑세스는 첫번쨰 컬럼만으로 이루어지게되어
인덱스를 탄 효과가 적을 듯 하네요.
로컬 인덱스로 만들었다면 아무 문제가 없었지 않았을까 생각됩니다.

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