ELK ( ElasticSearch, LogStash, Kibana) 스택을 써서 MySQL의 1600만건이 넘는 책 데이터를
Grok 필터 플러그인을 써서 마이그레이션 해서 테스트 중이다
(1630만건 데이터 Logstash로 마이그레이션 하는데 대략 51분 43초 정도 걸렸다)
Date의 경우 filter에서 String 값을 ISO 기준 Date 형태로 변환해줘서 넣어주긴했는데 애초에 발간년도, 등록년도, EL 등록TimeStamp 등으로 나눠지니 컨트롤하기 번거롭긴 하다
(그냥 epoch_millis Type 정도로 해두고 로그조사 페이지 만들때처럼 서버단에서 SimpleFormat 해줄까 하는 생각도 듦)
리턴되는 Row 값이 많아질 수록 확실히 엘라스틱서치가 빠르긴 한데
(대략 10만 Row당 Fulltext Indexing한 MySQL은 0.400 mills, 노리 형태소 분석기로 분석한 엘라스틱서치는 0.050 mills 정도 나온다)
책 데이터, 그 중에서도 더럽기 이를데 없는 Title 필드는 굉장히 세팅을 하기가 힘들었다
nori 형태소 분석기를 사용하는데 먼저 책의 경우 전체 타이틀명을 검색할 경우를 생각해서
nori analyzer의 decompound_mode를 mixed로 설정했는데 책 타이틀 특성 상 원체 나눠지는 term이 많다보니
max_shingle_size의 default max 값인 3으로는 안될 것 같았다
(전체 텀을 합친 기존 검색어를 만들지 못해서 keyword 필드로 검색해야 하는 귀찮음이 발생한다. 사용자 경험에 악영향을 줄거라고 생각해서 다른 방법을 생각해보기로 했다. 물론 이부분도 서버단에서 다른 SEQ을 날려 multi field를 타게 하면 되겠지만, 아직 스프링단에서 EL로 expression 쿼리 날리는건 익숙하지가 않다)
그래서 따로 index.max_shingle_diff 값을 세팅을 통해 5정도로 설정해주고
(term_vector 로 1600만 데이터 타이틀 색인으로 엄청 느려질게 무서워서 5정도만 했다. 근데 5도 row 한개 당 termvector에 쌓이는 데이터들을 보니 무서움)
max_result_window 값 default가 10000밖에 안되길래 row가 많을 때 1만개만 불러와서 RDB와의 속도 비교 테스트가 안되서 100만 정도로 쿨하게 풀어줌
(실제 상용화 서비스를 진행할 때는 물론 속도나 ux를 위해 default 값 또는 그보다 낮게 두고 서버 단에서 page 쪽에 limit를 걸어줄 생각이다)
쨋든 이런식으로 인덱스를 만들어서 데이터를 넣고 테스트 했는데, 이놈이 또 analyze를 노리 분석기로 하니까 검색 단어를 멋대로 쪼개서 검색해버림 (전체 타이틀을 검색하면 그 검색어를 자기 멋대로 쪼갬;)
그래서 그냥 색인만 nori로 하고 검색 analyze는 유저나 내가 생각하기 편하게 standard로 나눠준 뒤 인덱스를 새로 만들어서 테스트 해봤다
원하던대로 풀 타이틀, 쪼갠 글자들로 검색이 잘되긴 한다
(max_shingle_size 필터를 5까지 풀어서 term을 최대 5개까지 합쳐서 색인 termvector를 만들도록 했는데 안되면 이상하다. 나으 귀중한 컴퓨터 리소스를 그토록 쳐먹게 만들었는데...)
문제는 편하게 하려고 서버단에서 jpa로 contains 검색을 통해 EL로 SEQ을 날리는데 띄어쓰기가 들어가면 contains 메소드가 오류를 뿜어냄
처음에는 서버단에서 Criteria 등을 사용해 확장 쿼리를 날릴까 하다가 stackoverflow에도 같은 문제로 "당신 덕분에 해결됬어요 고마워요!" 하는 답댓이 없길래, 삽질이 될 것을 우려해서 그냥 View단에서 받은 검색어 String의 빈 공백을 서버에서 포멧팅하고 EL DB 자체적으로 Term 들을 shingle filter에서 합치는 작업에서 token_seperator로 공백문자열을 없애서 텀들을 합치게 만들었다.
(이렇게 하면 유저들은 띄어쓰기를 했지만 DB는 띄어쓰기가 없는 텀을 검색하게 될 테니까 ㅇㅅㅇ)
이렇게 띄어쓰기 문제는 해결했는데 막상 해보니까 느리다
색인이 너무 많아져서 그런 것 같아서 타이틀 필드에서 현재 성능과 검색 편의성의 사이에서 계속해서 인덱스 설정이나 맵핑을 어떻게 할 지 조율중이다