“인덱스를 만들었는데 왜 안 타요?” SQL 튜닝에서 가장 자주 나오는 질문이다. 답을 알려면 인덱스가 어떤 모양으로 정렬되어 있는지부터 봐야 한다. SQLD의 SQL 최적화 기본 원리 단원과 정보관리기술사 데이터베이스 영역에서 인덱스 구조와 “인덱스를 사용하지 못하는 경우”는 단골 주제다.
책에서 “트랜잭션”이라는 단어를 찾을 때 첫 쪽부터 넘기지 않고 찾아보기에서 쪽수를 확인한다. 인덱스도 같다. 키 값을 정렬해 두고, 각 키가 가리키는 행의 위치(Oracle에서는 ROWID)를 함께 저장한다. 대부분의 RDBMS가 기본으로 쓰는 인덱스는 B-Tree 계열(실제 구현은 B+Tree 변형이 많다)이다.
다음처럼 가정해 보자. 테이블에 1억 행이 있고 한 블록에 100행이 들어가며, 인덱스 블록 하나에 키가 약 200개 들어간다. 숫자는 설명을 위한 가정이다.
다만 조회 행이 많아지면 얘기가 달라진다. 인덱스로 읽은 행마다 테이블 블록에 랜덤 접근이 생기므로, 처리 범위가 넓으면 풀 스캔이 더 빠를 수 있다. 그 기준선은 DBMS와 데이터 분포에 따라 다르다.
| 인덱스를 못 쓰는 조건 | 이유 | 고치는 방향 |
|---|---|---|
WHERE SUBSTR(name,1,1)='김' 처럼 컬럼에 함수 적용 | 인덱스는 원래 컬럼 값으로 정렬되어 있어 가공된 값은 정렬 순서가 다름 | name LIKE '김%' |
WHERE sal*12 > 36000000 | 좌변 컬럼을 연산함 | sal > 3000000 (상수 쪽으로 연산 이동) |
LIKE '%김' 처럼 앞쪽 와일드카드 | 첫 글자가 정해지지 않아 어느 지점부터 읽을지 알 수 없음 | 검색 요건 재검토, 별도 검색 설계 |
| 문자 컬럼을 숫자와 비교하는 묵시적 형변환 | 컬럼 쪽이 변환되면 컬럼 가공과 같은 결과가 됨(DBMS별 규칙 상이) | 비교 대상의 타입을 컬럼에 맞춤 |
부정 조건(<>, NOT IN) | 범위를 좁혀 주지 못해 대부분 읽게 됨 | 가능하면 긍정 조건으로 변환 |
| 결합 인덱스의 선두 컬럼 조건 누락 | 정렬이 선두 컬럼 기준이라 뒤 컬럼만으로는 위치를 특정할 수 없음 | 선두 컬럼 조건 추가, 컬럼 순서 재설계 |
NULL도 함정이다. Oracle의 단일 컬럼 B-Tree 인덱스는 모든 키가 NULL인 행을 저장하지 않아 IS NULL 조건에 쓰이지 못하는 경우가 있다. 제품마다 동작이 다르므로 시험에서는 “DBMS에 따라 다르다”는 단서를 붙이는 편이 안전하다.
(부서코드, 입사일) 순서로 만든 인덱스를 생각해 보자. 부서코드가 같은 행끼리 모여 있고 그 안에서 입사일 순으로 정렬된다. 그래서 부서코드='A' AND 입사일 BETWEEN ...은 좁은 구간만 읽지만, 입사일 조건만 있으면 부서마다 흩어져 있어 효율이 떨어진다. 일반적으로 등치(=) 조건 컬럼을 앞에, 범위 조건 컬럼을 뒤에 두고, 조건에 자주 쓰이는 컬럼을 우선한다.
인덱스는 정렬된 키로 한 길을 내려가 찾는 구조이므로, 키 컬럼을 가공하거나 선두 컬럼을 건너뛰면 그 정렬을 쓸 수 없다.
이 글은 학습용 정리이며 실제 시험 문항과 다를 수 있다. 출제 기준은 한국데이터산업진흥원, 큐넷 등 공식 공지를 확인하라. 그림은 개념도이며 실측 데이터가 아니다.
환자 1,000명 중 암 환자가 20명뿐인 데이터로 모델을 만들었는데 정확도가 98%라면 훌륭한 모델일까? 안타깝게도 "모두…
코드를 고칠 때 한 군데만 바꿨는데 엉뚱한 곳이 줄줄이 깨진 경험이 있다면, 그것이 결합도가 높은…
두 스레드가 같은 변수를 동시에 고치면 결과가 실행할 때마다 달라진다. 이 문제를 푸는 도구가 세마포어와…
사내 시스템에 한 번 로그인했는데 파일 서버, 메일, 인트라넷이 비밀번호를 다시 묻지 않는다면 뒤에서 커버로스(Kerberos)가…
11월에 일정이 있는 금융 DT 테스트 시험을 정리했습니다. 접수, 시험, 합격 발표 날짜를 한 번에…