본문 바로가기
Database/MYSQL

MySQL_5.7의 n-gram

by 반화넬 2018. 5. 9.
반응형

MySQL5.6부터는 InnoDB에서도 전문검색이 가능하기는 하였지만 공백 기준으로 단어들이 파싱이 되는 “MeCab Full-Text Parser Plugin” 방이라 아쉬움이 많았다. 특히 한국말처럼 공뱁만으로 단어를 파싱할수 없는 그런 언어들이 있기때문이죠.

그런데 MySQL 5.7부터는 n-gram 방식의 전문 검색 인덱스를 지원하면서, 한국어/중국어/일본어에서도 효율적인 전문 검색이 가능하게 되었습니다. 물론 mroonga와 같은 Third party 스토리지 엔진을 설치해서 사용을 할 수 있겠지만.. 백업/복구가 늘 이슈가 늘 따라죠.

알아보고자 하는건 N-GRAM 이죠 

메뉴얼 내용을 인용하면, 컨텐츠의 인덱스를 아래와 같이 첫글자/두글자..(1그램,2그램,3그램..) 등등으로 나누어서 파싱하여 전문검색 인덱스를 만드는 것이라고 생각하면 됩니다.

  5.7 이하에서는 공백을 기준으로 분할 했었죠mysql 에서 sql 검색시에는 검색이 안되었지만 ..



N-GRAM  사용햇을경우는 최소 토큰 사이즈(ngram_token_size)는 2이고, 위에서 “n=2″ 부터 토큰을 만들게 됩니다. 당연한 이야기겠지만, n-수치가 낮을수록 토큰 수가 많아질 것이기에, 모든 검색어들이 3글자부터 시작된다면 이 수치를 3으로 상향 조정하는 것도 인덱싱 관리 및 사이즈 안정성에 도움이 됩니다.

  n=1: 'a', 'b', 'c', 'd'
  n=2: 'ab', 'bc', 'cd'
  n=3: 'abc', 'bcd'
  n=4: 'abcd'

# mysql 검색시 검색이 된다

mysql> SELECT * FROM articles WHERE MATCH(title) AGAINST('sql' IN BOOLEAN MODE);
+------------+--------+
| FTS_DOC_ID | title  |
+------------+--------+
|          1 | my sql |
|          2 | my sql |
|          3 | mysql  |
+------------+--------+
3 rows in set (0.00 sec)


와일드 카드를 사용한 검색

접두사 (prefix)가 ngram_token_size 보다 작은 경우, 검색 결과는 그 접두사로 시작하는 n-gram 토큰을 포함한 모든 행을 반환합니다.


mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST ('s*' IN BOOLEAN MODE);
+------------+--------+
| FTS_DOC_ID | title  |
+------------+--------+
|          1 | my sql |
|          2 | my sql |
|          3 | mysql  |
|          4 | sq     |
|          5 | sl     |
+------------+--------+
5 rows in set (0.00 sec)

접두사 길이가 ngram_token_size과 같거나 큰 경우 와일드 카드를 사용한 검색은 구문 검색으로 변환되고 와일드 카드는 무시됩니다. 예를 들어, ‘sq *’는 ‘ “sq”‘로 변환되어 ‘sql *’는 ‘ “sq ql”‘로 변환됩니다.


mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST ('sq*' IN BOOLEAN MODE);
+------------+--------+
| FTS_DOC_ID | title  |
+------------+--------+
|          1 | my sql |
|          2 | my sql |
|          3 | mysql  |
|          4 | sq     |
+------------+--------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST ('sql*' IN BOOLEAN MODE);
+------------+--------+
| FTS_DOC_ID | title  |
+------------+--------+
|          1 | my sql |
|          2 | my sql |
|          3 | mysql  |
+------------+--------+
3 rows in set (0.00 sec)


구문 검색

구문 검색은 n-gram 토큰 문구 검색으로 변환됩니다. 예를 들어, “sql”는 “sq ql”로 변환됩니다.


mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST('"sql"' IN BOOLEAN MODE);
+------------+--------+
| FTS_DOC_ID | title  |
+------------+--------+
|          1 | my sql |
|          2 | my sql |
|          3 | mysql  |
+------------+--------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST ('"my sql"' IN BOOLEAN MODE);
+------------+--------+
| FTS_DOC_ID | title  |
+------------+--------+
|          1 | my sql |
|          2 | my sql |
+------------+--------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST ('"mysql"' IN BOOLEAN MODE);
+------------+-------+
| FTS_DOC_ID | title |
+------------+-------+
|          3 | mysql |
+------------+-------+
1 row in set (0.00 sec)

InnoDB의 전문 검색 전반에 관하여 자세히 알고 싶다면, 사용자 설명서 InnoDB Full-Text Index 부분과 Jimmy의 기사 (Dr. Dobb’s article)를 참조하십시오. N-gram 파서 대한 자세한 내용은 사용자 설명서의 N-gram parser 부분을 참조하십시오.


반응형