데이터 저장 구조
index, table, LOB 컬럼 모두 하나의 세그먼트로 표현된다.
특정 컴포넌트가 너무 커지면, 해당 세그먼트가 EXTENT를 추가로 할당 받는다.
EXTENT는 연속된 블록의 모음이다.
또한 db 테이블을 파티션하면, 하나의 파티션이 하나의 세그먼트로 들어갈 수 있다.
multi block IO → 한번에 인접한 블록 여러개 가져오기 == 같은 extent 내에 있는 블록 가져오기 이다( 다른 extent에 있는 것 까지 가져오기 불가능)
library cache: 쿼리 캐싱. 소프트 파싱을 위함
buffer cache: 실제 데이터 캐싱. 굳이 disk에서 데이터 가져오지 않고 캐싱된 데이터 가져올 수 있다
만약 1,2,3,4,5,6,7 번 블록이 있는데, 캐시에 1,5,7만 들어있다면?
1,5,7 은 캐싱된 데이터 가져온다.
2,3,4 는 multi block IO로 가져오고, 6은 single block io로 가져온다.
scan 방식
1) 테이블에서 가져오는 방식
1-1) table full scan
테이블 전체를 스캔해서 read.
꼭 table full scan이 나쁜게 아니다. 오히려 index range scan이 실제 sql 성능 떨어트리는 경우도 매우 많다.
1-2) index range scan
index에서 일정량 스캔해 얻은 ROWID(테이블 레코드의 디스크 상 위치 정보)로 테이블 레코드를 찾아나가는 방식.
오히려 index range scan의 성능이 나쁜 경우가 많다.
대량의 데이터에 대해서는 index가 full scan 보다 불리하다.
특히 한번에 데이터를 다수 처리하는 집계용 sql, batch 로직들이 그렇다. 이런 경우는 table full scan으로 유도하면 오히려 성능이 빨라진다.
또한, join 포함 할 경우, hash join으로 유도해주면 성능이 매우 개선된다.
왜 인덱스 쓰면 오히려 느릴까?
위에서 설명한 block io 방식 (single, mutli) 을 참고하자.
index range scan은 single block I/O 사용하기 때문이다. ( random access + single block IO)
반면, 테이블 full scan은 multiblock I/O로 한번에 다수를 가져온다. (serial access + multi block IO)
따라서, index 써서 실제 테이블 데이터를 index tree를 통해 효율적으로 읽어 온다 하더라도, 가장 병목이 되는 block IO에서 시간이 더 걸려서, 의미가 없어진다.
== 물리적 IO 많이 발생
또한, 한번 읽었던 블록을 반복해서 읽는 비효율도 발생한다 .
만약 한 블록에, 500개레코드가 있다면, 같은 블록을 최대 500번 읽을 수 있다. ( 해당 블록 내에 있는 index의 500개 레코드가, single block IO로 500번 중복 접근)
반면, full scan은 각 블록을 무조건 1번씩만 읽는다.
== 논리적 IO 많이 발생
인덱스는, 대량의 데이터 중, '소량의 데이터를 필터링 해 가져올 떄' 강력한 것이지, 대량의 데이터 가져올 때는 나쁜 방법이다!
'sql튜닝' 카테고리의 다른 글
3장 - 인덱스 튜닝 (0) | 2025.02.19 |
---|---|
sql 최적화 - 2장 인덱스 - index scan 종류 (0) | 2025.02.19 |