Skip to content
isdnetworks
Go back

조건을 더해도 인덱스를 못 타는 형태

느린 쿼리에 조건을 하나 더 넣고 실행 계획을 다시 봤더니 여전히 전체를 읽고 있었다. 인덱스가 있는 컬럼인데도 타지 않는 형태가 있어서 그 형태를 갈래별로 나눠 봤다.

Table of contents

Open Table of contents

함수로 감싼 컬럼

날짜 함수로 컬럼을 감싼 조건이었는데 인덱스는 원래 값으로 만들어져 있어 함수를 거친 값을 찾지 못한다. 같은 조건을 범위 비교로 바꾸니 수백만 건 전체 스캔이 수만 건 범위 스캔으로 내려갔다.

컬럼은 그대로 두고 상수 쪽을 조정하는 것이 이 갈래의 원칙이 됐다. 조건이 하나 더 붙었다는 사실만으로는 인덱스를 타는 근거가 되지 않는다.

같은 모양의 열네 곳

연도 추출과 대문자 변환과 부분 문자열 추출까지 같은 모양을 코드 전체에서 찾으니 열네 곳이 나왔다. 각각 범위 조건과 저장 시점 정규화와 앞부분 일치로 바꿔서 인덱스를 타게 만들었다.

앞부분 일치는 시작하는 값이 정해져 있으므로 인덱스로 좁힐 수 있다. 대문자 변환은 조회 시점이 아니라 저장 시점에 통일해 두는 편이 조회 조건을 단순하게 만든다.

타입 불일치가 만드는 암묵 변환

문자열 컬럼을 숫자로 비교하면 데이터베이스가 컬럼 쪽을 숫자로 바꿔서 비교하므로 함수를 씌운 것과 같아진다. 따옴표를 붙여 문자열끼리 비교하게 하니 같은 쿼리가 인덱스를 탔다.

이 갈래는 쿼리문만 봐서는 잡히지 않고 값을 넘기는 코드까지 같이 봐야 한다. 애플리케이션이 정수 변수를 그대로 넘기면 쿼리 문자열에는 아무 흔적도 남지 않기 때문이다.

앞 와일드카드와 구조 변경

앞에 와일드카드가 붙은 부분 일치는 시작하는 값을 모르므로 인덱스로 좁힐 방법 자체가 없다. 이것은 조건을 고쳐서 풀리는 문제가 아니라 검색 구조를 바꿔야 하는 문제였다.

앞부분 일치로 요건을 줄이는 안과 전문 검색을 붙이는 안과 자주 찾는 값을 따로 담는 안 셋에서 골랐다. 상품명 검색이라 요건을 줄일 수 없어서 전문 검색 쪽으로 갔다.

매칭 건수가 지우는 인덱스의 의미

두 조건이 하나로 묶인 자리에서는 각각 인덱스가 있어도 옵티마이저가 나누지 못하면 전체를 읽었다. 두 조건을 별개 쿼리로 나눠 합치니 각자 인덱스를 타면서 계획이 바뀌었다.

정산 시각이 비어 있는지를 보는 조건은 다른 이유로 인덱스가 의미를 잃고 있었다. 대부분의 행에서 그 값이 비어 있어 인덱스로 좁혀도 남는 건수가 전체와 크게 다르지 않았기 때문이다.

정리


Share this post on:

Previous Post
규격 대조가 배제한 원인 후보
Next Post
무한 반복이 된 자동 재시작