-- 조건절 1
where C1 = 'B'
-- 조건절 2 (스캔량 줄임)
where C1 = 'B'
and C2 = 3
-- 조건절 3 (스캔량 줄임)
where C1 = 'B'
and C2 >= 3
-- 조건절 4 (스캔량 줄임)
where C1 = 'B'
and C2 <= 3
-- 조건절 5 (스캔량 줄임)
where C1 = 'B'
and C2 between 2 and 3
-- 조건절 6 (스캔량 줄이는데 역할 못함)
where C1 = between 'A' and 'C'
and C2 between 2 and 3
비용
= 인덱스 수직적 탐색 비용 + 인덱스 수평적 탐색 비용 + 테이블 랜덤 액세스 비용
= 인덱스 루트와 브랜치 레벨에서 읽는 블록 수 + 인덱스 리프 블록을 스캔하는 과정에서 읽는 블록 수 + 테이블 액세스 과정에서 읽는 블록 수
테이블과 달리 인덱스는 같은 값을 갖는 레코드들이 군집해 있음.
첫번째 나타나는 범위검색 조건까지만 만족하는 인덱스 레코드는 모두 연속해서 모여 있지만, 그 이하 조건까지 만족하는 레코드는 비교 연산자 종류에 상관없이 흩어진다.
where C1 = 1 and C1 = 'A' and C3 = '나' and C4 = 'a'
where C1 = 1 and C1 = 'A' and C3 = '나' and C4 >= 'a'
where C1 = 1 and C1 = 'A' and C3 between '가' and '다' and C4 = 'a'
where C1 = 1 and C1 <= 'B' and C3 ='나' and C4 between 'a' and 'b'
인덱스 컬럼을 조건절에 모두 등치(=) 조건으로 사용할 때 효율이 가장 좋다.
where 아파트시세코드 = :a
where 아파트시세코드 = :a and 평형 = :b
where 아파트시세코드 = :a and 평형 = :b and 평형타입 = :c
where 아파트시세코드 = :a and 평형 = :b and 평형타입 between :c and :d
반면, 인덱스 선행 컬럼이 조건절에 없거나 부등호, BETWEEN, LIKE 같은 범위검색 조건이면, 인덱스를 스캔하는 단계에서 비효율이 발생
select 해당층, 펑당가, 입력일, 해당동, 매물구분, 연사용일수, 중개업소코드
from 매물아파트매매
where 아파트시세코드 'A01011350900056'
and 평형 = '59'
and 평형타입 = 'A'
and 인터넷매물 between '1' and '3'
order by 입력일 desc
- 인덱스 : 아파트시세코드 + 평형 + 평형타입 + 인터넷매물
인덱스 선행 컬럼이 모두 '='조건일 때 필요한 범위만 스캔하고 멈출수 있는 것은 조건을 만족하는 레코드가 모두 한데 모여 있기 때문
- 인덱스 : 인터넷매물 + 아파트시세코드 + 평형 + 평형타
인덱스 선두 컬럼 인터넷매물에 BETWEEN이 사용되어서 나머지 조건을 만족하는 레코드들이 뿔뿔이 흩어진다.
select 해당층, 평당가, 입력일, 해당동, 매물구분, 연사용일수, 중개업소코드
from 매물아파트매매
where 인터넷매물 in ('1', '2', '3')
and 아파트시세코드 'A01011350900056'
and 평형 = '59'
and 평형타입 = 'A'
order by 입력일 desc
아 안돼.. 머.. 멈춰!!!
선두 컬럼이 BETWEEN이어서 나머지 검색 조건을 만족하는 데이터들이 서로 멀리 떨어져있을 때 Index Skip Scan의 위력이 나타난다.
select * from 고객별가입상품
where 고객번호 = :cust_no and 상품id in ('NH00037', 'NH00041', 'NH00050')
select * from 고객별가입상품
where 고객번호 = :cust_no and 상품id = 'NH00037'
union all
select * from 고객별가입상품
where 고객번호 = :cust_no and 상품id = 'NH00041'
union all
select * from 고객별가입상품
where 고객번호 = :cust_no and 상품id = 'NH00050'
/*+ num_index_keys(테이블 컬럼 명 n) */
select * from 월별고객별판매집계
where 판매월 like '2019%'
select * from 월별고객별판매집계
where 판매월 between '201901' and '201912'
where 판매월 between '201901' and '201912'
and 판매구분 = 'B'
where 판매월 like '2019%'
and 판매구분 = 'B'
where 판매월 between '201901' and '201912'
and 판매구분 = 'A'
where 판매월 like '2019%'
and 판매구분 = 'A'
select 고객ID, 상품명, 지역코드, ...
from 가입상품
where 회사코드 = :com
and 지역코드 = :reg
and 상품명 like :prod || '%'
select 고객ID, 상품명, 지역코드, ...
from 가입상품
where 회사코드 = :com
and 상품명 like :prod || '%'
select 고객ID, 상품명, 지역코드, ...
from 가입상품
where 회사코드 = :com
and 지역코드 like :reg || '%'
and 상품명 like :prod || '%'
UNION ALL 방식은 옵션 조건 컬럼도 인덱스 액세스 조건으로 사용한다는 사실이 중요하다.
NULL 허용 컬럼이더라도 사용하는데 문제 없음.
유일한 단점은 코딩량이 길어진다.
PL/SQL 함수는 개발자들이 일반적으로 생각하는 것보다 매우 느리다.
회원 테이블을 Full Scan 하는 방식으로 읽는것과, 인덱스를 통해 일부 또는 한번만 호출하도록 인덱스 구성을 잘 하면 함수 호출을 최소화 할 수 있다.
select * from 회원 a where 암호화된_전화번호 = encryption(:phone_no)
create index 회원_X03 on 회원 (생년, 암호화된_전화번호);