
LIKE 연산자는 범위 조건을 비교하기 위해 주로 사용합니다.
select *
from 월별고객판매집계
where 판매월 like '2019%'
between 또한 범위 조건을 비교하기 위해 주로 사용합니다.
select * from 월별고객판매집계
where 판매월 between '201901' and '201912'
LIKE와 BETWEEN은 둘 다 범위 검색 조건이므로, 사용할 때의 비효율 원리가 똑같이 적용됩니다. 하지만 테이블의 데이터분포와 조건절의 값에 따라 인덱스 스캔량이 달라집니다. 일반적으로 LIKE 조건보다 BETWEEN 조건을 사용하는 것이 효율적입니다.
-- 판매구분 컬럼의 값은 A와 B 두 개의 값이 존재하고, 각각 9:1의 비중을 차지한다.
-- 조건절 1
WHERE 판매월 BETWEEN '201901' AND '201912'
AND 판매구분 = 'B'
-- 조건절 2
WHERE 판매월 LIKE '2019%'
AND 판매구분 = 'B'
조건절 1은 판매월이 201901이고 판매구분이 B인 레코드에서 스캔을 시작합니다. 반면 조건절 2는 판매월이 201901 인 첫 번째 레코드에서 스캔을 시작합니다. 판매월이 201900 인 데이터가 존재하지 않는다는 것을 사람은 알지만 엔진은 알 수 없기 때문입니다. 조건절 2의 인덱스 스캔량이 조건절 1보다 많습니다.
-- 판매구분 컬럼의 값은 A와 B 두 개의 값이 존재하고, 각각 1:9의 비중을 차지한다.
-- 조건절 3
WHERE 판매월 BETWEEN '201901' AND '201912'
AND 판매구분 = 'A'
-- 조건절 4
WHERE 판매월 LIKE '2019%'
AND 판매구분 = 'A'
조건절 3은 판매월이 201912이고 판매구분이 B인 레코드를 만나면 스캔을 멈춥니다. 반면 조건절 4는 판매월 = 201912인 레코드를 모두 스캔하고 난 후 멈춥니다. 202913의 존재를 인간은 알지만 엔진은 모르기 때문입니다. 이에 LIKE 조건을 사용한 조건절 4의 인덱스 스캔량이 더 많습니다.
LIKE 조건을 남용할 때 생기는 비효율
실제 쿼리를 개발할 때 선택적인 입력값을 처리하기 위해 like ' :value || '%' ' 구문을 사용하는 경우가 많습니다. 이런 방식의 LIKE 조건남용은 비효율을 유발합니다.
-- index [회사코드 + 지역코드 + 상품명]
-- 쿼리 1 : 회사코드, 지역코드, 상품명을 모두 입력할 때
SELECT 고객ID, 상품명, 지역코드, ...
FROM 가입상품
WHERE 회사코드 = :com
AND 지역코드 = :reg -- 선택조건
AND 상품명 LIKE :prod || '%'
-- 쿼리 2 : 회사코드, 상품명만 입력할 때
SELECT 고객ID, 상품명, 지역코드, ...
FROM 가입상품
WHERE 회사코드 = :com
AND 상품명 LIKE :prod || '%'
인덱스의 중간칼럼인 지역코드에 대한 조건이 없다면 어쩔 수 없이 넓은 범위를 스캔하지만 중간칼럼이 있으면 세 칼럼 모두 액세스 조건이므로 효율적으로 스캔할 수 있습니다. 다음의 쿼리는 선택조건을 표현하기 위해 LIKE 조건을 사용합니다.
SELECT 고객ID, 상품명, 지역코드, ...
FROM 가입상품
WHERE 회사코드 = :com
AND 지역코드 LIKE :reg || '%'
AND 상품명 LIKE :prod || '%'
지역코드를 입력했을 때 like 조건으로 인해 쿼리 1보다 스캔 범위가 늘어납니다. 쿼리 1에서 액세스 조건이던 상품명이 쿼리 3에서 필터조건으로 바뀌면서 생긴 변화입니다.
결과적으로 개발편의성을 위해 인덱스 칼럼에 범위검색 조건을 남용하면 인덱스 스캔 비효율이 발생합니다. 특히, 대량의 테이블을 넓은 범위로 검색할 때 그 영향이 매우 클 수 있습니다. 데이터 분포에 따라 인덱스 칼럼에 대한 비교 연산자를 신중하게 선택해야 합니다.
'DB > SQL튜닝' 카테고리의 다른 글
| SQL튜닝 - PL/SQL 함수호출로 인한 부하를 줄이는 인덱스 구성방법 (0) | 2024.01.23 |
|---|---|
| SQL 튜니이론 - 다양한 선택조건 처리방식 OR EXPANSION, LIKE/BETWEEN, UNION ALL, NVL/DECODE, DYNAMIC QUERY (0) | 2024.01.23 |
| SQL튜닝이론 - IN 조건과 등치조건(=) 의 비교 (0) | 2024.01.22 |
| SQL튜닝이론 - 인덱스스캔 효율화 방안 (0) | 2024.01.19 |
| SQL 튜닝이론 - 인덱스 탐색의 비효율을 유발하는 범위검색조건절 (0) | 2024.01.18 |