두개의 쿼리 성능면에서 비교 좀 해주세요~ 0 6 2,152

by 박민석 [2009.06.15 10:50:22]


보통 최근 데이타를 보기 위해 2) 번과 같이 쿼리를 많이 날립니다. 그런데 마이그레이션 후 데이타가 존재 유무를 확인하기 위해 1)번과 같이 쿼리를 한번 날렸는데 결과가 나오는데 한세월 걸리더군요~~ ㅠㅠ

대부분의 데이터 rec_uk 값이 들어 있고 ATVT_DRU_DT 컬럼은 거의 100% 데이터가 들어 있습니다. 때문에 금방 나올거라 생각했는데.. 1) 번의 경우 기다리다 지쳐 중간에 끊었습니다.

2)번의 경우는 금방 나오구요~~

 COM_ATVT_NU02 는 ATVT_DRU_DT + column01으로 이루어진 인덱스 입니다.

 이거 혹시 왜 이런지 설명 가능할까요? 제 상식으로는 도저히 이해가 안가네요..

 

 1) 힌트 미사용

select * from COM_ATVT
where ATVT_DRU_DT < ’99999999999999’
and rec_uk is not null and rownum <100;

Execution Plan
--------------------------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=18M Card=99 Bytes=16K)
   1    0   COUNT (STOPKEY)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF ’COM_ATVT’ (TABLE) (Cost=18M Card=2M Bytes=234M)
   3    2       INDEX (RANGE SCAN) OF ’COM_ATVT_NU02’ (INDEX) (Cost=75K Card=18M)

 

 2) 힌트 사용

select /*+ index_desc(COM_ATVT COM_ATVT_NU02) */ * from COM_ATVT
where ATVT_DRU_DT > ’00000000000000’ and
rec_uk is not null and rownum<100

 Execution Plan
--------------------------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=18M Card=99 Bytes=16K)
   1    0   COUNT (STOPKEY)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF ’COM_ATVT’ (TABLE) (Cost=18M Card=2M Bytes=234M)
   3    2       INDEX (RANGE SCAN DESCENDING) OF ’COM_ATVT_NU02’ (INDEX) (Cost=75K Card=18M)

by 이재현 [2009.06.15 11:57:51]
커리를 조금만 고쳐서 해보셔영

select * from COM_ATVT
where ATVT_DRU_DT < ’99999’
and rec_uk is not null and rownum <100;

이렇게 하시구 나오는 데이타(ATVT_DRU_DT + column01) 정렬이.. ASC인지 DESC

인지확인하시구요

아마 ASC로 나올거 같아요

select /*+ index_desc(COM_ATVT COM_ATVT_NU02) */ * from COM_ATVT
where ATVT_DRU_DT > ’00000000000000’ and
rec_uk is not null and rownum<100


애하구 비교해보셔영..

제 생각인되 1번은 DESC된거를 ASC로 보여줄라구 다시 정렬을해서느린거 같구요

2번은 걍 순차적으로 보여주니깐 빠르다구생각 드네용

그럼 수고영

PS 잘못된 지식일수있으니 여러 경로로 알아 보심이.


by 박민석 [2009.06.15 12:50:21]
참고로 아래의 쿼리 둘다 힌트를 사용하지 않았던 1) 번과 같은 결과 입니다.
도대체가 이해가 안가네요..ㅠㅠ

select /*+ INDEX_asc(COM_ATVT COM_ATVT_NU02) */ * from COM_ATVT
where ATVT_DRU_DT > '00000000000000' and
rec_uk is not null and rownum<100;

select /*+ INDEX(COM_ATVT COM_ATVT_NU02) */ * from COM_ATVT
where ATVT_DRU_DT > '00000000000000' and
rec_uk is not null and rownum<100;

by 마농 [2009.06.15 13:02:10]
인덱스 스캔을 한후에 Rowid를 가지고 테이블스캔을 다시 합니다.
그런다음 조건체크(rec_uk is not null)를 합니다.
이때 atvt_dru_dt 가 작은 쪽의 rec_uk 는 널값이 많구요.
반대로 atvt_dru_dt 가 큰 쪽의 rec_uk 는 널값이 거의 없습니다.
작은 일자부터 차례로 읽을 경우 (rec_uk is not null)인 자료를 찾기위해 100건이 아닌 더 많은 자료를 읽어 와야지만 100건을 채울 수 있습니다.
반대로 큰 일자부터 차례로 읽는 다면 거늬 모든 행이 조건에 부합하므로 100건정도만 테이블을 읽으면 100건을 채울 수 있습니다.

by 마농 [2009.06.15 13:07:04]
다시 말하면 인덱스 순서대로 읽을 경우 읽혀진 행중에 대부분이 조건에 맞지 않아 버려지게 됩니다.
읽어들인 데이터 중에 버려질 데이터들이 남겨질 데이터 보다 상대적으로 많아서 100건을 읽어들이기 위해 테이블의 거의 모든 데이터를 읽어야 하는 상황이 될수도 있습니다.

by 박민석 [2009.06.15 13:07:40]
마농님 답변이 정답입니다.
저도 하도 이상해서 방금 데이터를 다시 확인 해봤는데..
그 짧은 사이에 마농님의 정확한 답변이 달려 있네요~~ ^^
아주 예전 초창기 데이터에는 rec_uk 필드가 null 인 경우가 대부분이더라구요~~
마농님 감사 합니다..

by 호야 [2009.06.15 16:41:47]
prodba의 에이스 님이시다..ㅋㅋㅋ
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입