시소당
- 전체 테이블 스캔 : 테이블에 있는 모든 로우들을 읽어내는 방법
- ※ 옵티마이져가 전체 테이블 스캔을 하게 되는 경우
- 적용가능 인덱스의 부재 : Query 상에서 인덱스를 전혀 사용할 수 없는 경우.
- 조건절의 컬럼이 인덱스에 포함되어 있지 않거나, 결합인덱스의 선두 컬럼이 존재하지 않을 때, 인덱스는 존재하지만 가공이 발생되어 인덱스를 사용할 수 없게 된 경우가 해당.
- 넒은 범위의 데이터 액세스 : 옵티마이져는 비록 적용가능한 인덱스가 존재하더라도 처리 범위가 넒어서 전체테이블 스캔이 보다 적은 비용이 든다면 인덱스 스캔을 포기할 수 있음
- 소량의 테이블 엑세스
- 병렬처리 엑세스 : 병렬처리는 전체 테이블 스캔을 더욱 효과적으로 수행하게 되므로 옵티마이져는 병렬처리로 수행되는 실행계획을 수립할 때 항상 풀 테이블 스캔을 선택함.
- ’Full’ 힌트를 적용했을 때 : Query 내에서 Full 힌트를 사용하는 경우.
- 다중 블록단위로 메모리에 옮겨지며, 이블록들을 순차적으로 읽혀진다.
- 한번에 엑세스 하는 블록의 양을 B_FILE_MULTIBLOCK_READ_COUNT 파라미터에서 지정한다(삼성예ㄱㄱ싱)
로우식별자(ROWID)스캔
- 단 하나의 로우를 테이블에서 추출하는 가장 빠른 방법
- 로우의 이주(Migration)나 체인(Chain), import/export에 의해서 변경 될 수 있으므로 리터럴 값으로 직접 사용하지 말고 바인드 변수를 사용할 것
- ※ ROWID는 그 로우를 포함하고 있는 데이터파일과 데이터블럭, 그리고 블록 내에서의 위치를 가지고 테이블에서 데이터를 추출하는 가장 빠른 방법
- 대부분의 ROWID 스캔은 인덱스를 경유하여 테이블을 엑세스하는 과정에서 발생함.
인덱스 스캔
- 인덱스 유일스캔(Index Unique Scan)
- 단 하나의 ROWID를 추출함
- 인덱스가 기본키나 Unique Index로 생성되어 있어야함
- 구성된 모든 컬럼이 조건절에서 ‘=‘로 비교되어야함.
- 인덱스 범위스캔(Index Range Scan)
- 가장 보편적인 데이터 엑세스 형태
- 시작점을 찾을땐 랜덤엑세스, 그 이후부터 종료까지는 스캔을 함.
- 즉, 브랜치 블록을 경유하여 시작 리프 블록을 찾은 후 계속 연결된 다음
- 하나 이상의 인덱스 선행 컬럼에 상수나 변수로 조건이 부여되어야 함
(비교연산자, Between LIKE) 등이 가능함.
- 단, LIKE 연산자의 선두에 ‘%’ 와 같은 와일드카드가 있을 경우 범위 스캔을 적용하지 않음
- 인덱스 역순범위스캔(Index Range Scan Descending)
- 인덱스 범위스캔과 엑세스 형태는 동일하나 역순으로 데이터를 엑세스한다
- ORDER BY ~ DESC 를 사용하거나 INDEX_DESC 힌트를 사용하여 적용함
- 스캔의 시작점이 최대값이 되고, 역순으로 리프 블록을 스캔하여 최소값이 될때까지 수행 (예를 들어 시간!).
- 엑세스 개수 보다 +1가의 스캔을 수행함(마지막건을 읽어야 범위가 끝났음을 알 수있음 (만화책 비유 끝 이거)
인덱스 스캔(계속)
- 인덱스 스킵 스캔(Index Skip Scan)
- 기존 인덱스의 선두칼럼을 참조하지 않으며 가끔 발생하는 쿼리를 위한 인덱스 추가를 줄여 줄 수 있다. 즉, 과다한 인덱스로 인한 DML저하를 방지하는 부분에서 매우 유용한다.
- 유도 칼럼이 아닌 칼럼에 대한 추가 인덱스 없이 쿼리 성능을 향상시킴.
- 프리픽스 칼럼에 구별 값이 비교적 적은 경우, 전체 테이블스캔보다 빠르다.
즉, 프리픽스 칼럼의 구별 값이 적고 다음 칼럼의 구별 값이 많을 때 좋다.
- 논리 서브인덱스를 구성하므로 인덱스를 직접 읽는 것보다는 빠르지 않다.
- 클러스터 인덱스, 내림차순 인덱스 스캔, CONNECT BY 절을 지원하며 리버스 키, 비트맵 인덱스, 도메인 인덱스와 함수기반 인덱스에 대해서는 지원하지 않는다.
- 인덱스의 선행 컬럼이 사용되지 않더라도 상위의 각 분기된 가지별로 주어진 조건 컬럼을 스캔(예제 ㄱㄱ싱)
인덱스 스캔(계속)
- 인덱스 전체 스캔(Index Full Scan)
- 조건절에서 그 인덱스 컬럼이 적어도 하나 이상 사용되었을 때 적용이 가능
즉, 반드시 선행컬럼이 사용되어야 할 필요는 없다.
- 쿼리내에 사용된 어떤 테이블들의 모든 컬럼들이 그 인덱스에 모두 존재하고, 인덱스 컬럼 중에서 최소한 NOT NULL인 컬럼이 하나는 존재 할때 사용 (예제 ㄱㄱ싱)
- 인덱스 고속 전체스캔(Index Fast Full Scan)
- 쿼리를 위해 사용한 어떤 테이블의 컬럼이 모두 그 인덱스에 포함되어 있을때 전체 테이블 스캔의 대안으로 사용한다
- 비트맵 인덱스에는 적용할 수 없다.
- INDEX_FFS / NO_INDEX_FFS 힌트로 조절 가능하다(예제 ㄱㄱ싱)
- 인덱스만을 스캔하고 테이블을 엑세스 하지 않는다.(그러니까 촐라빠름?)
- 인덱스 전체 스캔과는 다르게 마치 테이블 엑세스처럼 한 번의 I/O에 다중 블록을 엑세스 함.