Skip to content
isdnetworks
Go back

옵티마이저가 안 쓰는 인덱스

특정 상태의 행을 뽑는 쿼리가 느렸는데 그 컬럼이 들어 있는 복합 인덱스가 있었다. 실행 계획을 보니 그 인덱스를 타지 않고 전체를 읽고 있었다.

Table of contents

Open Table of contents

선두 컬럼이 조건에 없었다

복합 인덱스는 왼쪽부터 순서대로 쓰이므로 선두 컬럼으로 먼저 정렬되고 그 안에서 다음 컬럼으로 정렬된다. 내 조건에는 두 번째 컬럼만 있었다.

그러면 어느 선두 구간에 있는지를 모르므로 인덱스 전 구간을 훑어야 한다. 컬럼이 인덱스에 들어 있다는 것과 그 인덱스를 탈 수 있다는 것은 다르고 옵티마이저는 그럴 바에 전체 스캔을 고른다.

세 가지 선택지

조건에 선두 컬럼을 추가하는 안은 값의 종류가 적을 때 되지만 모든 값을 알아야 하고 새 값이 생기면 놓친다. 단독 인덱스를 만드는 안은 가장 직접적이지만 인덱스가 늘고 쓰기가 조금 느려진다.

인덱스를 강제하는 안은 대개 답이 아니었다. 옵티마이저가 안 쓰기로 한 데는 이유가 있고 선두 컬럼이 없으면 강제해도 인덱스 전체를 훑게 된다.

조회 빈도가 정한 선택

어느 쪽으로 갈지 정하려고 이 조회가 얼마나 자주 도는지를 봤다. 화면에서 쓰는 것이 아니라 배치에서 하루 몇 번이었다.

그러면 인덱스를 하나 더 만드는 비용이 이득보다 클 수 있다. 조회 빈도가 대응을 가르므로 같은 증상이라도 화면에서 초당 도는 쿼리였으면 반대로 갔을 것이다.

원래 있어야 했던 조건

조건에 선두 컬럼을 넣는 방향으로 가면서 값 목록을 하드코딩하지 않을 방법을 찾다가 의미 쪽을 봤다. 이 배치는 승인된 것만 대상이므로 승인 상태 조건이 원래 있어야 했다.

그 조건을 넣으니 인덱스를 타면서 결과도 더 정확해졌다. 성능 문제로 시작했는데 빠뜨린 조건 하나가 원인이었던 셈이다.

복합 인덱스 설계 순서

이후로 복합 인덱스를 만들 때 등호 조건에 쓰는 컬럼을 앞에 두고 범위 조건을 뒤에 둔다. 값의 종류가 많아 잘 걸러 내는 컬럼을 앞에 두고 정렬에 쓰는 컬럼을 뒤에 둔다.

그리고 어떤 조회가 이 인덱스를 탈지를 목록으로 적어 둔다. 실행 계획의 예상 행 수는 추정치이므로 실제 매칭 수를 따로 세어 크게 어긋나면 통계 갱신을 본다.

정리


Share this post on:

Previous Post
죽여도 다시 뜬다
Next Post
배치가 정상 경로와 같은 상태를 만들어야 한다