MySQL Index - Full text search

MySQL Index - Full Text Search

MySQL의 LIKE 를 쓸 때에 '%HELLO%' 로 검색하게 된다면, 인덱스를 사용하지 않게 된다. B-Tree 인덱스는 실제 칼럼의 앞부분만 사용하기 때문이다.

그렇다면 문자열 검색은 영원히 Full Scan만을 해야하는 것일까? 라는 물음에, Full Text Search를 답할 수 있다. 오늘 Real MySQL 책의 내용은 Full Text Search 알고리즘 및 사용법이다.


인덱스 알고리즘

키워드를 인덱싱하는 기법에 따라 아래 2개로 나뉨


어근 분석 알고리즘

Stop Word 처리

stop word : 자주 등장하지만 분석을 하는 것에 있어서는 큰 도움이 되지 않는 단어 참고

MySQL 코드에 stop word 가 정의되어 있고, 사용자가 정의해서 처리할 수도 있다.

확인방법

information_schema.innodb_ft_default_stopword 테이블에서 확인 가능.


Stemming (어근 분석)

검색어로 선정된 단어의 뿌리인 원형을 찾는 작업. MySQL에서는 MeCab 이라는 플러그인 형태로 지원한다.

한글을 분석할 수 있도록 하기에는 많은 비용이 든다.


n-gram 알고리즘

MeCab 는 만족할만한 결과를 내기 위해서 많은 비용을 써야하기에 n-gram 은 그 단점을 보완하기 위해 도입됐다.

n-gram : 본문을 무조건 N글자씩 잘라서 인덱싱하는 방법

N글자로 글자를 잘라서 토큰을 만들고, 해당 토큰들 중에서 stop word를 필터링하는 방식. 그 후 토큰들을 B-Tree 인덱스에 저장한다.


Full Text Search Query

예시 테이블 tb_test

CREATE TABLE tb_test (
  doc_id INT,
  doc_body TEXT,
  PRIMARY KEY (doc_id),
  FULLTEXT KEY fx_docbody (doc_body) WITH PARSER ngram
) ENGINE=InnoDB;


Full Scan Query - Bad Case

SELECT *
FROM tb_test
WHERE doc_body LIKE '%문서%';

→ table full scan


Full Text Search Query - Good Case

SELECT *
FROM tb_test
WHERE MATCH(doc_body) AGAINST('문서' IN BOOLEAN MODE);

→ 위 예제처럼 MATCH (...) AGAINST (...) 로 작성을 해야하고, MATCH 안에 full text search 컬럼들을 모두 명시해야한다.


느낀점

이전에 해커톤에서 관련 인덱스를 쓴적이 있는데.. 그 때는 급해서 일단 좋아보이니깐 썼으나 이런 특징이 있다는 것을 알게되어 다행인듯..