쿼리 성능 측정 체크리스트
1. 인덱스 사용 가능 여부
- WHERE ID IS NULL 처럼 NULL 조건만 있는 경우 인덱스 사용이 불가능하다. 쿼리 참조 컬럼은 인덱스 안에 저장되어 있어야 한다.
2. 인덱스 범위 스캔 가능 여부
- 부정형 비교는 인덱스 사용 불가능 (ex: where id <> 'test', WHERE id is not null)
- 인덱스 컬럼을 가공하면 인덱스 사용 불가
- 묵시적 형 변환하는 경우 숫자형과 문자형 비교 시 숫자형 우선시 됨
3. 인덱스 스캔이 풀스캔보다 효율적인지 확인
- 인덱스 스캔은 rowid에 의해 데이터를 랜덤하고 single block read 전략을 가지는 엑세스이고, 테이블 풀스캔은 sequential 한 방식으로 multi block read 전략을 가지고 데이터에 엑세스한다. 만약 읽을 데이터가 sequential하게 모여있지 않아 여러 블록으로 분산된 경우 single block 단위로 여러번 i/o 발생하므로 정능 저하를 가져온다.
4. pk 인덱스로 조인하는지
- pk인덱스로 NL조인 할 경우 driving table에는 하나의 row만 선택하게 된다. 하지만 inner table에 엑세스 될 때는 random 엑세스 부하가 만만찮다.
5. 인덱스 컬럼의 distinct value 갯수가 적은지
- 비트맵 인덱스 사용 고려 필요.
6. 인덱스 선행조건 체크리스트
- 인덱스 선행 조건은 = 조건이 아니면 비효율 발생.
- 인덱스 선행 컬럼이 조건에 누락되었는지, between, 부등호, like 같은 범위 검색 조건이 사용되었는지
7. 선행 조건이 범위 검색이라면, between을 in-list로 변환 가능한지
- 선행조건 컬럼이 범위 값 탐색이라면 비효율이 발생한다.
8. 범위 조건이 여러개인지
- 범위 조건이 여러개라면 첫 범위 조건에 의해 스캔 범위가 결정되며, 그 다음부터는 스캔 범위를 줄이는데 크게 기여하지 못하므로 성능상 불리할 수 있다. 이 경우 범위를 나눠 union all 하는 것이 더 빠를 수 있다.
9. like를 between으로 바꿀 수 있는지
- between을 사용하면 스캔 범위를 줄일 수 있다.
10. 두개의 부등호를 사용하여 데이터 검색이 필요한지
선분이력( 조회일자 >= 시작일 and 조회일 <= 종료일 과 같은 두 부등호 사용하는 것) 의 두번째 부등호 조건은 스캔 범위를 줄이는데 도움을 주지 못하므로 어느 시점을 주로 조회하느냐에 따라 인덱스 전략을 달리 가져가야 한다. 최근 데이터 조회 시 종료일 후 시작일로, 과거 데이터 조회 시 시작일 후 종료일로
11. 정렬이 필요한 경우
- order by 절에 인덱스 구성 컬럼을 기술
12. 테이블 조인 시 인덱스를 각 테이블이 가지고 있는지
- 적절한 인덱스가 없다면 소트머지 조인이나 해시 조인이 실행되므로 NL조인이 유리한 경우 인덱스에 조인 컬럼 추가 필요
13. 서브 쿼리 사용여부
- 메인쿼리: 서브쿼리 = m:1 관계 일 시 JOIN으로 변환 후 최적화한다.
14. OR 조건 사용 여부
- WHERE a = 'hi' or b = 'hello' 의 경우
WHERE a = 'hi' UNION ALL WHERE b = 'hello' 로 변환하여 사용하는 것이 인덱슬ㄹ 사용하여 더 효율적이다.
15. 범위 검색 혹은 바인드 변수 사용 시
- 컬럼 타입과 맞는지 확인 필요. 날짜의 경우 to_date, 바인드의 경우 to_char