MySQL

MySQL Full Text Search Index 사용하기

RyanGomdoriPooh 2017. 5. 18. 15:51

전문 검색(Full Text Search)은 검색 기능을 서비스에 도입하고 싶은 분들에게 필요한 기능입니다.


기존의 인덱스와 다른 방식의 인덱스입니다.


MySQL의 B-Tree Index ( 보통 그냥 Index 라고 불림 )

: Index의 경우에는 한 컬럼 안에서 비슷한 형식의 데이터 중에서 원하는 데이터를 찾는 경우 사용하는 것이 일반적입니다.


예를 들면,

위도, 경도, 나이 등등, 비슷한 특정한 범위 안에서 데이터를 찾을 수 있게 인덱싱을 도와주는 경우입니다.

위도 -90.0~+90, 경도 -180~+180, 나이 0~150


MySQL의 Full-text Index ( 보통 Full-text Index 라고 부름 )

: Full-text Index의 경우에는 한 컬럼 안에서 많은 형태의 데이터가 담겨있어서 효율적으로 데이터를 찾는 경우 사용하는 것이 일반적입니다.


예를 들면,

컨텐츠 내용과 같이 사용자가 쓰기 나름인 데이터를 토큰 단위로 쪼개서 검색에 용이하게 합니다.

컨텐츠 내용 : "나는 오늘 seoul의 sky를 바라보면서 베스킨라빈스31에서 맛있는 요리를 먹었다! 정말 기분 좋았다." 와 같이 한글, 영어, 숫자가 섞여 있거나 긴 내용을 검색할 때 사용됩니다.




그럼 이제부터 Full-text Index를 사용하는 방법에 대해서 이야기해보겠습니다.



Full-text Index의 데이터를 인덱싱하는 기법

: 데이터를 인덱싱하는 이유는 사용자가 검색하게 될 키워드를 빠르게 검색할 수 있게 하기 위해서 다음 두 가지 종류의 parser를 이용해서 인덱스를 구축합니다.


1) Built-in parser 또는 Stop-word parser
    - Stop-word 기법을 사용하는 기본 내장 파서(built-in parser)를 이용합니다.
    - Stop-word는 토큰을 나눌때 해당하는 Stop-word가 나타났을 때 기준으로 토큰을 나눕니다.
    - 예를 들면,
    Input : "나는 매일이 지옥 같았습니다.
    Stop-word : “ ”(공백) => 공백은 디폴트 값입니다.
    Token : 나는 | 매일이 지옥 같았습니다.
    공백을 기준으로 4개의 토큰이 인덱싱 되었습니다.

2) N-gram parser
    - n-gram 기법을 사용하여 할당한 토큰의 크기 n만큼씩 데이터를 인덱스로 파싱해두었다가 사용하는 파서입니다.
    - 예를 들면, 
    Input : “나는 김치찌개가 좋습니다.”
    N-gram : n=2
    Token : 나는 | 는  |  김 | 김치 | 치찌 | 찌개 | 개가 | 개  |  좋 | 좋습 | 습니 | 니다 | 다. => 중에서 Token 2가 아닌 “는 “,” 김”, “개 “, “ 좋” 은 제거됩니다.

                나는 | 김치 | 치찌 | 찌개 | 개가 | 좋습 | 습니 | 니다 | 다. => 로 인덱싱 되었습니다.

위 그림 예시에서도 er과 ra는 n-gram parsing은 되었지만 인덱싱 되지 않습니다.



N-gram Full-text Index 생성 과정

: 1) 인덱스 대상 문서 => 1) n글자로 구성된 서브 그룹 => 2) 백엔드 인덱스 => 3) 인덱스 대상 서브 그룹 => 4) 2-Gram 서브 그룹 => 5) 프론트엔드 인덱스 : 생성


1) 인덱싱 대상 문서를 n-gram 의 n보다 큰 값의 토큰으로 서브 그룹을 나눕니다. 아래 그림에서는 4크기의 토큰으로 정하고 서브그룹을 구성했습니다.

- 서브그룹 생성 방식은 해당 문서 데이터의 왼쪽을 시작으로 4글자 토큰을 만들고 토큰의 마지막 글자부터 다시 4글자 토큰을 만들어서 데이터의 끝까지 생성.

- 각 문서에 대한 4글자 토큰 서브그룹을 생성 해줍니다.


2) 위 1) 단계에서 추출된 서브그룹 중에서 중복되는 서브그룹별로 토큰 분류하고, 백엔드 인덱스를 만듭니다.

- 중복되지 않는 4글자로 구성된 서브그룹 리스트를 만듭니다. 그래서 백엔드 인덱스를 만드는데에 사용합니다.

- 백엔드 인덱스에 중복되지 않는 4글자로 구성된 서브 그룹을 활용해서 백엔드 인덱스에 문서위치와 같이 생성을 합니다.

- 문서위치는 해당 서브그룹이 1)에서 위치하는 곳에 (문서번호,문서열번호)를 넣습니다.


3) 백엔드 인덱스에서 중복되지 않은 서브그룹에서 다시한번 n-gram용 서브그룹을 만듭니다.


- 각 서브그룹을 다시 한번 2-gram 방식으로 서브그룹을 2글자 토큰으로 나눕니다.

- n-gram 토크나이징 방식은 왼쪽부터 1글자씩 오른쪽으로 이동하면서 연속된 n글자로 토큰을 구성합니다.

- ex) 가나다라마 일때, n=2    =>    가나,나다,다라,라마

    n=3    =>    가나다,나다라,다라마

    n=4    =>    가나다라,나다라마


4) 3)과정에서 생성된 2-Gram 토큰을 분류하고, 중복되지 않은 2-Gram 서브 그룹을 생성합니다.


5) 3), 4) 과정에서 n-gram 방식으로 토크나이징한 서브그룹 정보를 이용해서 프론트엔드 인덱스를 생성합니다.

- 프론트엔드 인덱스에서 서브 그룹과 그룹 위치로 구성을 합니다.

- 그룹 위치는 3) 과정 인덱스 대상 서브그룹에서 (서브그룹번호,서브그룹열번호) 로 구성됩니다.



N-gram Full-text Index 검색 과정


1) 인덱스의 검색 과정은 생성되는 반대로 입력된 검색어를 n-gram의 n바이트 단위로 동일하게 자른다.

ex) "마바사"를 검색합니다.

1) 마바    2) 바사    를 동일하게 자릅니다.


2) 동일하게 자른 검색용 n-gram 토큰을 이용해서 프론트엔드 인덱스를 검색한다.

ex) 프론트엔드 인덱스에서 마바(1,1), 바사(1,2) 정보를 검색하였습니다. => 그룹위치의 행#이 마바에서 1, 바사에서 1이므로 서브그룹 1이 이 토큰에 연관.

3) 검색된 결과 정보를 백엔드 인덱스의 검색 대상 후보 리스트로 두고, 백엔드 인덱스를 통해서 최종 확인을 거쳐 일치하는 결과를 가져옵니다.

ex) 프론트엔드 인덱스에서 찾아낸 서브그룹 정보 1(="라마바사")로 문서 위치를 찾는다.

최종적으로 "마바사"의 위치는 서브그룹 정보 1인 "라마바사"의 정보 (0,1),(1,2)에서 행인 0,1의 문서0,문서1을 찾습니다.



Stop-word parser와 N-gram parser의 비교

1) 검색 속도

- 검색어 바이트 수가 많아질수록, 쿼리 실행 시간이 Stop-word parser > N-gram parser 입니다. 즉, N-gram 검색이 빠릅니다.


2) 인덱스 용량

- 저장 데이터 바이트 수가 많아질수록, 인덱스 스토리지 사용량은 Stop-word parser < N-gram parser 입니다. 즉, N-gram이 더 많은 용량을 사용합니다.



Full-text Search 검색 쿼리

: Full-text Search 쿼리는 다음 쿼리를 사용해야합니다.

"SELECT * FROM "테이블명" WHERE MATCH("검색할컬럼명"[, ...]) AGAINST('"검색할키워드식" "검색모드");



검색 모드의 종류

1) 자연어 검색(natural search)

- 검색 문자열을 단어 단위로 분리한 후, 해당 단어 중 하나라도 포함되는 행을 찾는다.

ex) SELECT * FROM “테이블명" WHERE MATCH (“검색컬럼명") AGAINST (‘맛집' IN NATURAL LANGUAGE MODE);


2) 불린 모드 검색(boolean mode search)

검색 문자열을 단어 단위로 분리한 후, 해당 단어가 포함되는 행을 찾는 규칙을 추가적으로 적용하여 해당 규칙에 매칭되는 행을 찾는다.
검색의 정확도에 따라 결과가 정렬되지 않는다.
구문 검색이 가능하다.
필수(+), 예외(-), 부분(*), 구문(“ ") 연산자를 사용할 수 있다
ex) SELECT * FROM “테이블명" WHERE MATCH (“검색컬럼명") AGAINST (‘+대구*+닭*+맛집*' IN BOOLEAN MODE);

3) 쿼리 확장 검색(query extension search)
- 2단계에 걸쳐서 검색을 수행한다. 첫 단계에서는 자연어 검색을 수행한 후, 첫 번째 검색의 결과에 매칭된 행을 기반으로 검색 문자열을 재구성하여 두 번째 검색을 수행한다. 이는 1단계 검색에서 사용한 단어와 연관성이 있는 단어가 1단계 검색에 매칭된 결과에 나타난다는 가정을 전제로 한다.



이상으로 글을 마치겠습니다.