B-Tree 인덱스는 기본적으로 오름차순 정렬 되기 때문에 왼쪽 값을 기준으로 오른쪽 값이 정렬된다. 이러한 특징으로 인해 특정 LIKE 조건을 사용할 때 인덱스를 적용할 수 없다.
1. LIKE '%mat'
2. LIKE '_mat'
3. LIKE '%mat%'
email 칼럼에 인덱스 설정을 해준다.
해당 인덱스를 기반으로 조회를 진행할 때는 저장된 값의 왼쪽 부터 한 글자씩 비교해가며 일치하는 레코드를 찾아간다.
만약 아래와 같은 쿼리를 처리한다고 가정할때
위 쿼리는 인덱스 레인지 스캔 방식을 사용할 수 없다. 이유는 email 칼럼에 저장된 값의 왼쪽부터 한 글자씩 비교해가며 일치하는 레코드를 찾아야 하는데, 조건절에 주어진 값은 왼쪽 부분이 고정되어 있지 않기 때문이다.
실제 실행 계획을 살펴보아도 풀 테이블 스캔을 진행하는 것을 확인할 수 있다.
mysql> EXPLAIN SELECT * FROM members m WHERE m.email LIKE '%mat%';
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | m | NULL | ALL | NULL | NULL | NULL | NULL | 9421768 | 11.11 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
Full Text search
그렇다면 특정 문자열을 포함하는 레코드를 조회하기 위해서는 무조건 풀 테이블 스캔을 진행해야 하는가? MySQL의 InnoDB나 MyISAM은 문서 전체에 대한 분석과 검색을 위한 인덱싱 알고리즘인 전문 검색(full text search)을 제공한다. 전문 검색을 활용하면 앞서 언급한 특정 LIKE조건에 인덱스를 활용할 수 있는 대안이 될 수 있다.