관련도 검색을 하려고 한다. 검색은 게시글 검색
우리 서비스에선 제목, 본문, 치료영역, 나이 이렇게 내용이 있음.
: 역인덱스 저장 + 역인덱스 탐색
<일반 인덱스>
| Idx | Value |
|---|---|
| 1 | 컴퓨터 |
| 2 | 컴퓨터 |
| 3 | 키보드 |
| 4 | 마우스 |
| 5 | 모니터 |
<역인덱스>
| 역인덱스 | Value |
|---|---|
| 컴퓨터 | 1,2 |
| 키보드 | 3 |
| 마우스 | 4 |
| 모니터 | 5 |
: 글자를 세글자씩 쪼개는 것
Ex. 개발의 신이 될거예요
=> 개발의 / 발의" " / 의 신 / " "신이 / 신이" " / 이" "될 / " "될거 / 될거예 / 거예요
<일반 인덱스>
| Idx | Value |
|---|---|
| 1번 | "컴퓨터마우스" |
| 2번 | "컴퓨터키보드" |
| 3번 | "키보드마우스" |
<역인덱싱>
| 역인덱스 | Value |
|---|---|
| 컴퓨터 | 1,2 |
| 퓨터마 | 1 |
| 터마우 | 1 |
| 마우스 | 1,3 |
| 터키보 | 2 |
| 키보드 | 2,3 |
| 보드마 | 3 |
"컴퓨터마우스" => "컴퓨터"/"퓨터마"/"터마우"/"마우스"
"컴퓨터" → 1, 2
"퓨터마" → 1
"터마우" → 1
"마우스" → 1, 3
1번 게시글: "컴퓨터" "퓨터마" "터마우" "마우스" → 4개 겹침
2번 게시글: "컴퓨터" → 1개 겹침
3번 게시글: "마우스" → 1개 겹침
1번: 4/4 겹침 → similarity 1.0 (완전 일치)
2번: 1/4 겹침 → similarity 0.25
3번: 1/4 겹침 → similarity 0.25
근데 게시판은 여러 데이터들이 모여있음. 예를들어 제목, 본문, 치료영역, 나이
등등 정보들이 모여있는데, 이걸 어떻게 trigram으로 나눠서 GIN을 적용시킬까?
각 테이블(데이터) 마다 점수를 계산함. 하지만 해당 IDX 자료구조를 데이터 개수만큼 방문해야함. 이게 트레이드 오프. 이걸 통해 얻을 수 있는건 가중치를 다르게 줘서 제목이 중요하다면 제목 가중치를 올리면 되는것. 커스텀이 가능함.
score = similarity(p.title, :kw) * 3.0 -- 제목 일치가 가장 중요
+ similarity(p.content, :kw) * 1.0 -- 본문은 보조
+ therapyArea_score * 1.5 -- Java 매핑값
+ ageGroup_score * 1.0 -- Java 매핑값
하지만 현재 서비스에서는 2번으로 진행하고, 후에 정확도가 필요하다고 판단되면 1번으로 리팩토링 할 예정
역정규화로 줄글로 모음 -> trigram -> GIN 진행
therapy_area = ART → "미술치료"
age_group = AGE_6_12 → "6세"
search_text = 제목 + " " + 본문 + " " + "미술치료" + " " + "6세"
여기서 트레이드 오프는 본문의 내용이 너무 길때가 문제가 된다.
만약 글자가 10000자라면 trigram은 9998개가 나옴. GIN 역인덱스에 9998개 엔트리 삽입해야함. 너무 큰 비용이라고 생각.
본문을 적을 때는, 앞에 중요 내용을 적을거라 생각하여 앞에서부터 100자만 포함하는 것이 합리적이라 생각.
제목 30자 + 본문 100자 + 치료영역 4자 + 나이 3자 => 약 150개의 trigram.
물론, 데이터 저장량이 훨씬 많음. 하지만 커뮤니티는 쓰기보다 읽기가 압도적으로 많을 것으로 예상됨. 따라서 검색의 FULL SCAN을 해결하고, 데이터를 좀 더 저장하는 편이 서비스차원에서 맞다고 생각함.
커뮤니티 서비스 특성상 쓰기보다 읽기가 압도적으로 많음
→ 시간-공간 트레이드오프에서 공간을 희생하고 시간을 얻는 것이 유리
→ search_text 역정규화 + GIN trigram 채택