이걸 쓴다쓴다 하면서 이제서야 써보네요....
루씬을 사용하여 데이터를 저장하고 조회 할 수 있도록 하였습니다.
검색어를 분석/통계 내는 프로그램인데
하루 몇십만건의 검색어와 그외 부가적은 데이터들을 색인하여 놓다보니..
이게 1년이 넘어가자 인덱스 파일의 크기가 10G를 훌쩍 넘어가버리더군요..
그래서 이번에 프로그램을 업그레이드 하면서
인덱스 파일을 년도별로 분리시키면서, 루씬에서 제공되는 MultiSearcher를 사용해보기로 하고
개발을 진행하였습니다.
1.단일 인덱스 파일로부터의 검색
그냥 기본적으로 검색을 한다고 하면 위와 같은 방식으로 검색을 하게 됩니다.
루씬에서 제공하는 MultiSearcher를 사용하기는 간단합니다.
위와 같은 단일 인덱스 파일로부터의 Searcher를 여러개 생성하여
이를 사용해서 MultiSearcher를 생성하게 됩니다.
그러면 인덱스를 어떻게 나눌 것인가..
저 같은 경우는 동일한 종류의 데이터셋을 년도로 나누어서 사용하려고 하지만
경우에 따라서는 블로그, 뉴스, 이미지 등 서로 성격이 다른 데이터를 색인한 인덱스 파일등을
MultiSearcher를 사용하여 한번에 검색을 하고 싶은 경우도 있을 것 입니다.
개인적인 생각으로는 MultiSearcher는 같은 종류의 색인 데이터를 분산 인덱스 파일로 만들었을 때
사용하는 것이 더 좋다고 생각합니다. 기본적으로 하둡과 같은 분산 파일 시스템에서의 검색을 위해
만들어진게 아닌가 싶기도 하고요..
일단 등록된 Searcher는 여러개이지만, 그 Searcher들을 통해 검색 할 쿼리와 정렬조건(랭킹 부스트등)은
하나의 쿼리로 날아가기 때문에, 블로그 , 뉴스, 이미지등을 모두 동일한 쿼리와 정렬 조건으로
검색을 하게 됩니다.
뉴스는 최신등록된 뉴스가.. 블로그는 hit가 많고 정확도가 높은 블로그가 더 많은 점수를 가지고 상위로
올라와야 할텐데.. MultiSearcher로는 기본적으로 저렇게 쿼리를 만들어 날리는 것이 쉽지 않기 때문입니다.
그리고 기본적으로 MultiSearcher는 각각의 Searcher부터의 검색 결과를 모두 받아와 그것을
주어진 쿼리식과 정렬식에 맞게 Merge를 하기 때문에 결과들이 전부 섞여 버릴 수도 있습니다.
만약 위와같은 검색을 하려면 그냥 멀티스레드로 단일 Searcher들을 통해서 각각 검색하여 그것을
나중에 취합하는 것이 더 좋을 것 입니다.
물론 각각의 검색 후 Merge의 과정 때문에 MultiSearcher의 사용은 아무래도
성능면에서 단일 Searcher를 통한 검색보다 떨어질 수 밖에 없을 것 입니다.
단일 인덱스 파일을 사용한다고 해도 저 같은 경우 현재 12기가가 넘는 인덱스 파일을 사용하여
검색을 하고 있는 상황인데 응답속도가 조금 떨어지기는 하여도 안정성에서는 큰 문제가
없다고 생각하고 있습니다. 그만큼 루씬이 정말 잘 만들어진 라이브러리라는 이야기도 되겠네요..:)
그럼에도 굳이 인덱스 파일을 나누려고 했던 이유는
일단 분석 데이터의 특징상 시간이 지난 데이터의 조회는 많이 떨어질 수 밖에 없는데
이것을 하나의 인덱스 파일에서 계속 같이 가지고 가기가 부담스러웠기 때문이고..
경우에 따라서는 불필요한 인덱스 파일은 백업을 받아 놓고 Current Index File 목록에서 날려버려서
성능의 향상을 가져 올 수도 있겠다 싶었습니다.
그리고 또 하나는 개인적인 호기심 때문이었습니다. 한번 사용해보고 싶었던...
이런저런 이유로 MultiSearcher를 사용하여 개발을 하게 되었지요...
그럼 MultiSearcher의 기본적인 사용을 보겠습니다.
2. MultiSearcher의 기본적인 사용
여러개의 디렉토리가 있고
이를 사용하여 IndexReader와 IndexSearcher를 생성하여 List에 넣고
이를 사용해 MultiSearcher를 생성합니다.
여기서 Reader를 따로 보관해두는 이유는
인덱스 파일이 변경되었을 경우 Reader를 사용하여 해당 인덱스를 다시 읽어야
변경된 내용을 검색 할 수가 있습니다. 그런데 MultiSearcher로 부터 해당 Searcher의
IndexReader를 받아 올 수가 없어서 불가피 하게 저런 방식을 사용하였습니다.
MultiSearcher로부터 SearchAble[]을 받아 올 수 는 있는데..
여기서부터 Reader를 받아 오는 것은 없더라구요.. SearchAble 추상클래스는 검색에 대한 API만 정의 되어 있고
getIndexReader라는 메서드는 IndexSearcher에서 따로 정의 되어 있는 메서드입니다.
혹은 있는 제가 API를 못 찾는 것인지도 모르겠습니다..^^
일단 간단한 사용은 위와 같이 사용이 가능합니다.
다음 글에서 IndexReader를 사용하여 인덱스 파일의 변경을 자동으로
감지하여 검색에 반영하는 로직과 정말로 데이터 결과를 정렬하여 Merge하는 코드를 개발하고
그리고 이를 테스트 할 수 있는 테스트 케이스를
만들어 보도록 하겠습니다.