2.1.1 미리보는 인덱스 튜닝
SQL 튜닝은 랜덤 I/O와의 전쟁
-. 데이터베이스 성능이 느린이유는 디스크 I/O 때문이다.
-. Disk I/O중에 랜덤 I/O가 중요
2.1.2 인덱스 구조
-. DBMS는 일반적으로 B*Tree 인덱스를 사용
※인덱스 탐색 과정
-. 수직적탐색 : 인덱스 스캔 시작점을 찾는 과정
-. 수평적탐색 : 데이터를 찾는 과정
2.1.5 결합 인덱스 구조와 탐색
-. 인덱스 선두 컬럼을 모두 "=" 조건으로 검색할 때는 어느 컬럼을 인덱스 앞쪽에 두든 블록 I/O 개수는 같으므로 성능도 같다.
-. Excel fillter 기능으로 착각하면 안된다.
-. B-Tree 구조로 되어 있는 Index는 루트에서 리프 블록까지 높이(dept)는 항상 같다.
2.2.2 인덱스를 Range Scan 할 수 없는 이유
-. 인덱스 컬럼을 가공하면 스캔의 시작점과 끝점을 찾을 수 없으므로 Range Scan을 할 수 없다.
-> ex> where nvl(주문수량, 0) < 100, where 생년월일 '20000101' and '20000201' , where 업체명 like '%대한%'
-. Or 구문(Where in 절도 마찬가지)도 마찬가지로 수직적탐색을 통해 어느 한 지점을 시작지점으로 바로 찾을 수 없다. 따라서 인덱스를 어떤 방식으로 구성해도 Range Scan을 할 수 없다.
-. where (전화번호 = :tel_no OR 고객명 = :cust_nm)을 아래와 같은 쿼리하면 Index Range Scan이 가능하다.
select * from 고객 where (전화번호 = :tel_no OR 고객명 = :cust_nm) |
select * from 고객 where 고객명 = :cust_nm union all select * from 고객 where 전화번호 = : tel_no and (고객명 <> : cust_nm or 고객명 is null); |
-- Hint를 사용할 경우 select/*+ use_concat */ * from 고객 where (전화번호 = :tel_no OR 고객명 = :cust_nm) |
2.2.3 더 중요한 인덱스 사용조건
-. 선행조건에 대한 이해 필요
-. ex) 인덱스 : [소속팀 + 사원명 + 연령] 순으로 구성
select 사원번호, 소속팀, 연령, 입사일자, 전화번호 from 사원 where 사원명 = '홍길동'; |
-. 위 인덱스의 구성은, 이름이 같은 사원이더라도 소속팀이 다르면 서로 Leap Block이 떨어져있게 된다. 이 조건으로 검색하면, 인덱스 스캔 시작점을 찾을 수 없고, 어디서 멈춰야 할지도 알 수 없다.
-. 인덱스를 Range Scan 하기 위한 가장 첫번째 조건은 인덱스 선두 컬럼이 조건절에 있어야한다.
2.2.7 자동 형변환
select * from 고객 where 생년월일 = 19821225 (문자형타입) (숫자형타입) -> 플랜에 보면 filter(TO_NUMBER("생년월일")= 19821225) -> 인덱스 컬럼을 가공했기 때문에 INDEX Range Scan을 사용할 수 없다. |
- Oracle에서 숫자형 vs 문자형 = 숫자형이 이김
- Oralce에서 날짜형 vs 문자형 = 날짜형이 이김
select * from 고객 where 가입일자 = '01-JAN-2018'; (날짜형타입) (문자형타입) -> 이 경우에는 날짜형 타입이 이기므로 인덱스를 사용하는데 문제 없다. |
select * from 고객 where 고객번호 like '%9410%'; -> like 자체가 문자열 비교 연산자이므로 이떄는 문자형 기준으로 숫자형 컬럼이 변환된다. |
2.3.2 Index Full Scan (first_rows)
-> 소트연산을 생략함으로써 전체 집합중 처음 일부를 빠르게 출력할 목적 -> first_rows(n) : 가장 좋은 응답 시간의 목표로 문 블록을 최적화하기 위해 cost-based 접근 -> n개의 row를 가져오는데 가장 response time이 작은것 , 페이징처리시 유용 -> SQL 문장에서 MAX, SUM, COUNT등과 같은 집합 함수를 사용하게 된다면 FIRST_ROWS 힌트는 무시된다 |
2.3.3 Index Unique Scan
-. 수직적 탐색으로 데이터를 찾는 스캔방식 -. Unique 인덱스라고 해도 범위검색 조건(between, 부등호, like)으로 검색할때는 Index Range Scan이 나타난다. |
2.3.4 Index Skip Scan
-. 인덱스 선두컬럼의 Distinct Value 개수가 적고 후행 컬럼의 Distinct Value 개수가 많을 때 유용 -. index_ss -> Skip Scan 유도 -. no_index_ss -> Skip Scan 방지 |
2.3.5 Index Fast Full Scan
-. Index Full Scan은 논리적으로 1 ~ 10 번 Block을 차례대로 읽음 -. Index Fast Full Scan은 물리적으로 디스크에 저장된 순서데로 읽음 1->2->10->3->9 ... -> 6 -. Multiblock I/O방식으로 읽음으로 디스크로 부터 대량의 인덱스 블록을 읽어야 할떄 큰 효과 -. 인덱스 키 순서대로 정렬 X -. 쿼리에 사용한 컬럼이 모두 인덱스에 포함돼 있을때만 사용 |
2.3.5 Index Range Scan Descending
-. 인덱스를 거꾸로 읽어서 값을 바로 가져온다. |
'Database > SQLP' 카테고리의 다른 글
[친절한SQL 6장] 기본 DML 튜닝 (0) | 2023.02.14 |
---|---|
[친절한 SQL 5장] 소트 튜닝 (0) | 2023.01.19 |
[친절한 SQL 4장] 조인튜닝 (0) | 2023.01.08 |
[친절한 SQL 3장] 인덱스 튜닝 (2) | 2022.12.26 |
[친절한 SQL 1장] SQL 처리 과정과 I/O (0) | 2022.12.05 |