MySQL(6)

오늘 배운 것

8.5 전문 검색 인덱스


지금까지 살펴본 인덱스 알고리즘은 일반적으로 크지 않은 데이터 또는 이미 키워드화한 작은 값에 대한 인덱싱 알고리즘이었다.

대표적으로 MySQL의 BTree인덱스는 실제 칼럼의 값이 1MB이더라도 1MB전체의 값을 인덱스 키로 사용하는 것이 아니라 1000바이트(MyISAM) 또는 3072바이트(InnoDB)까지만 잘라서 인덱스 키로 사용한다. 또한 BTree인덱스의 특성에서도 봤듯이, 전체일치 또는 좌측 일부 일치와 같은 검색만 가능하다.

문서의 내용 전체를 인덱스화해서 특정 키워드가 포함된 문서를 검색하는 전문(Full Text) 검색에는 일반적인 BTree 인덱스를 사용할 수 없다. 

문서 전체에 대한 분석과 검색을 위한 이러한 인덱싱 알고리즘을 전문검색(Full Text search) 인덱스 라고 하는데, 일반화된 기능의 명칭이지 전문 검색 알고리즘의 명칭을 말하는 것이 아니다.

8.5.1 full text search 의 인덱스 알고리즘

전문 검색에서는 문서 본문의 내용에서 사용자가 검색하게 될 키워드를 분석해 내고, 빠른 검색용으로 사용할 수 있게 이러한 키워드로 인덱스를 구축한다. 키워드의 분석 및 인덱스 구축에는 여러가지 방법이 있다.예전에는 구분자도 하나의 인덱싱 알고리즘으로 봤는데, 이미 어근분석과 n-gram 에 포함되도록 바뀌었다.

8.5.1.1 어근 분석 알고리즘

다음과 같은 두가지 중요한 과정을 거쳐서 색인 작업이 수행된다.

  1. 불용어(Stop word) 처리
  2. 어근 분석(Stemming)

불용어 처리는 검색에서 별 가치가 없는 단어를 모두 필터링 해서 제거하는 작업을 말한다. 불용어의 개수는 많지 않기 때문에 알고리즘을 구현한 코드에 모두 상수로 정의해서 사용하는 경우가 많고, 유연성을 위해 불용어 자체를 DB화 해서 사용자가 추가하거나 삭제할 수 있게 구현하는 경우도 있다. 현재 MySQL 서버는 불용어가 소스코드에 정의돼 있지만, 이를 무시하고 사용자가 별도로 불용어를 정의할 수 있는 기능을 제공한다.

어근 분석 은 검색어로 선정된 단어의 뿌리인 원형을 찾는 작업이다. MySQL 서버에서는 오픈소스 형태소 분석 라이브러리인 MeCab을 플러그인 형태로 사용할 수 있게 제공한다. 한글이나 일본어의 경우 영어와 같이 단어의 변형 자체는 거의 없어서 어근 분석보다는 문장의 형태소를 분석해서 명사와 조사를 구분하는 기능이 더 중요한 편이다.

사실 MeCab은 일본어를 위한 형태소 분석 프로그램이며, 서구권 언어를 위한 형태소 분석기는 MongoDB에서 사용하는 SnowHall이라는 오픈소스가 있다. 중요한것은 국가 언어가 다 다르므로 언어별로 방식이 다르고, 한국은 일본이랑 비슷해서 MeCab으로 한글 분석이 가능하다.

그러나 MeCab을 설치한다고 끝나는게 아니라 단어사전이 필요하며, 문장을 해체해서 각 단어의 품사를 식별할 수 있는 문장의 구조 인식이 필요하다. 이를 위해서는 실제 언어의 샘플을 이용해 언어를 학습하는 과정이 필요한데, 상당한 시간이 걸린다. 한글에 맞게 완성도를 갖추는 작업은 많은 시간과 노력이 필요하다.

8.5.1.2 n-gram 알고리즘

MeCan을 위한 형태소 분석은 많은 노력과 시간을 필요로 한다. 범용적으로 사용하기 어려워서 단점을 보완하기 위해 n-gram이 도입된 것이다.

형태소 분석이 문장을 이해하는 알고리즘이라면, n-gram은 단순히 키워드를 검색해내기 위한 인덱싱 알고리즘이다.

n-gram이란 본문을 무조건 몇 글자씩 잘라서 인덱싱 하는 방법이다. 형태소 분석보다는 알고리즘이 단순하고, 국가별 언어 이해와 준비작업이 필요 없는 반면, 만들어진 인덱스의 크기는 상당히 크다. 일반적으로 2-gram 을 많이 쓴다.

8.5.1.3 불용어 변경 및 삭제

불용어 처리가 도움이 되기보다는 혼란스럽게 하는 기능일 수도 있다. 그래서 처리 자체를 무시하거나, 내장 불용어 대신 사용자가 직접 등록하는 방법을 권장한다.

8.5.2 전문 검색 인덱스의 가용성

전문검색 인덱스를 사용하려면 반드시 다음 두가지 조건을 갖춰야 한다.

  1. 쿼리 문장이 전문 검색을 위한 문법 (MATCH…. AGAINST…)을 사용
  2. 테이블이 전문 검색 대상 칼럼에 대해서 전문 인덱스 보유

다음과 같이 테이블의 doc_body 칼럼에 대해 전문 검색 인덱스를 생성했다고 해보자.


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;

다음과 같은 검색 쿼리로도 원하는 검색결과를 얻을 수 있을 것이다. 하지만 전문 검색 인덱스를 이용해 효율적으로 쿼리가 실행된 것이 아니라 테이블을 처음부터 끝까지 읽는 풀 테이블 스캔으로 쿼리를 처리한다.

SELECT * FROM tb_test WHERE doc_body LIKE '%애플%'

전문 검색 인덱스를 사용하려면 반드시 다음 예제와 같이 MATCH ... AGAINST (...) 구문으로 검색 쿼리를 작성해야 하며, 전문 검색 인덱스를 구성하는 칼럼들은 MATCH 절의 괄호 안에 모두 명시해야 한다.

SELECT * FROM tb_test 
WHERE MATCH(doc_body) AGAINST('얘플' IN BOOLEAN MODE);

results matching ""

    No results matching ""