한 줄 정의
전문 검색(Full-text) 인덱스는 문서의 단어들을 토큰 단위로 분해 해 역색인을 만들어, 긴 텍스트에서도 키워드 검색을 빠르게 수행하게 해주는 인덱스입니다.
쉽게 말하면
일반 B-Tree 인덱스가 “이름 전체” 를 색인한다면, 전문 검색 인덱스는 “문장을 구성하는 각 단어” 를 따로 색인합니다.
“MySQL은 빠릅니다”라는 문장은 B-Tree에서는 하나의 값이지만, 전문 검색에서는 MySQL, 빠릅니다 두 개의 단어로 쪼개 색인됩니다. 덕분에 빠릅니다만으로도 이 문장을 찾을 수 있습니다.
왜 필요한가?
일반 인덱스는 문서 내 단어 검색에 전혀 도움이 되지 않습니다.
-- 인덱스: (content)
SELECT * FROM articles WHERE content LIKE '%MySQL%';이 쿼리는 앞에 와일드카드(%) 가 있어서 B-Tree 인덱스를 탈 수 없습니다. 결국 풀 스캔이 되고, 수백만 건의 문서에서는 사용 불가 수준으로 느려집니다. 전문 검색 인덱스는 이 문제를 해결합니다.
핵심 내용
토큰화 방식
전문 검색 인덱스는 문서를 어떻게 단어로 쪼갤 것인가 가 핵심입니다. MySQL InnoDB는 두 가지 파서를 지원합니다.
1. 기본 파서 (Built-in Parser)
공백과 특수문자 를 기준으로 단어를 분리합니다.
"MySQL is fast" → ["MySQL", "is", "fast"]
- 영어처럼 공백으로 단어가 구분되는 언어에 적합
- 한국어에는 부적합 (조사가 붙어있어 “MySQL은”과 “MySQL”을 다른 단어로 취급)
2. n-gram 파서
n글자씩 연속으로 잘라 토큰을 만듭니다.
"검색엔진" (n=2) → ["검색", "색엔", "엔진"]
- 공백이 없는 언어(한국어/일본어/중국어)에 적합
- n=2(bigram)가 기본이며 권장값
인덱스 생성 예
CREATE TABLE articles (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
content TEXT,
FULLTEXT INDEX ft_content (content) WITH PARSER ngram
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;전문 검색 쿼리
전문 검색 인덱스는 일반 WHERE가 아니라 MATCH ... AGAINST 구문으로 사용합니다.
-- 자연어 검색 (기본)
SELECT * FROM articles
WHERE MATCH(content) AGAINST('MySQL 인덱스' IN NATURAL LANGUAGE MODE);
-- 불리언 검색 (+포함, -제외, * 와일드카드)
SELECT * FROM articles
WHERE MATCH(content) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);검색 모드
| 모드 | 설명 |
|---|---|
| NATURAL LANGUAGE MODE (기본) | 자연어 질의, 연관도 점수 기반 정렬 |
| BOOLEAN MODE | +, -, * 등 연산자 사용 가능 |
| QUERY EXPANSION | 1차 결과에서 키워드 확장 재검색 |
불용어 (Stopword)
“the”, “is”, “a” 같은 자주 등장하지만 검색에 의미 없는 단어 는 인덱스에서 제외됩니다.
- 기본 불용어 목록이 내장되어 있으며 커스터마이징 가능
innodb_ft_enable_stopword설정으로 켜고 끌 수 있음- 한국어에서는 조사/어미가 불용어 역할을 할 수 있지만, n-gram 파서에서는 개념이 다름
최소 토큰 길이
기본적으로 3글자 미만의 단어는 인덱싱하지 않습니다.
- InnoDB:
innodb_ft_min_token_size(기본 3) - MyISAM:
ft_min_word_len(기본 4)
한국어처럼 2글자 단어도 의미 있는 경우, 이 값을 조정해야 합니다. bigram 기반이면 2로 맞추는 것이 일반적 입니다.
검색 결과의 연관도 (Relevance)
MATCH ... AGAINST는 boolean 값이 아니라 연관도 점수 를 반환합니다.
SELECT id,
MATCH(content) AGAINST('MySQL') AS score
FROM articles
ORDER BY score DESC
LIMIT 10;점수가 0이면 매치되지 않은 것이고, 양수면 관련된 문서입니다.
내 생각
-
실무에서 대규모 검색이 필요하다면 MySQL의 전문 검색 인덱스는 Elasticsearch의 대체재가 되기 어렵습니다. 형태소 분석, 동의어 처리, 점수 커스터마이징, 실시간 색인 업데이트 같은 기능이 훨씬 제한적입니다.
-
그럼에도 불구하고 “이미 MySQL에 있는 데이터에 대해 가볍게 검색 기능을 추가 해야 할 때”는 전문 검색 인덱스가 훌륭한 선택입니다. 별도 검색 엔진을 운영하는 비용을 생각하면, 중소 규모에서는 충분한 솔루션입니다.
-
한국어 환경에서는 반드시
WITH PARSER ngram을 사용해야 하며,innodb_ft_min_token_size = 2로 설정해야 2글자 단어도 검색됩니다. 기본값으로 사용하면 한국어 검색이 거의 동작하지 않습니다.
관련 개념
- Ch08-2 인덱스란 무엇인가 — 자료구조별 인덱스 분류
- Ch08-3 B-Tree 인덱스 —
LIKE '%...%'가 B-Tree를 못 타는 이유
출처
- Real MySQL 8.0 (1권), 8.5 전문 검색 인덱스