IndexSearcher는 Index의 변경 내용을 그 상태로는 인지 하지 못 합니다. 
주로 IndexWriter에 의해서 추가적인 색인이 되거나
IndexReader에 의한 삭제등이 될텐데요..
제가 구현하고 있는 프로그램도 하루에 한번 로그를  분석 후 색인을 추가하기 때문에
색인 파일 변경에 대한 감지를 하여 이를 처리 할 수 있어야 했습니다.

MultiSearcher를 사용했기 때문에
각 Searcher들이 바라보고 있는 Index파일들을 모두 체크하여
인덱스 파일이 변경되었을 경우 Index파일을 다시 열어서 IndexSearcher를 다시 생성하는
방법을 사용하기로 하였습니다.

각 Searcher별로 가지고 있는 IndexReader를 MultiSearcher로 부터는 직접적으로 얻을 수 없었기 때문에
IndexReader를 List에 담아 보관하고, IndexSearcher를 사용 할 때 마다 IndexReader로 Index파일을 체크하여
만약 하나라도 변경된 사항이 있으면, 현재 만들어진 MultiSearcher를 날려버리고 전부 새로 IndexSearcher를 생성하여
다시 MultiSearcher를 생성하는 방식을 사용했습니다.

세부적은 성능등은 고려하지 않았는데
사용자가 극 소수이고 트래픽도 많지 않았기 때문에 이정도로도 충분하더군요...

또한 IndexSearcher는 재사용 하는 것이 좋기 때문에 , MultiSearcher를 생성 후 
이를 Map에 담아두고 return해주는 방식으로 Manager 클래스를 구현하였습니다.



주요내용은 주석으로 적었습니다만.. 주요 골격은 Index 디렉토리로부터 Searcher들을 생성하여 이를 통해 MultiSearcher를 생성합니다. 그리고 재사용을 위해 Map에 저장하여 이것을 사용해 검색을 수행합니다.
현재로서는 default 라는 이름의 키만을 사용하게 되어있지요..
기본적으로 잘 다듬어진 코드는 아니지만 일단, 이정도로 Searcher를 사용하여 생성하고 있습니다.

만약, 구현하려는 부분에 짧은 주기의 색인 반영이나 Index 파일의 변경이 필요하다면
더 디테일한 구현이 필요 할 것 입니다.

이것을 테스트해보기 위해서
테스트 케이스를 작성해보았습니다.



상당히 간단한 테스트케이스입니다.
실제 정렬이라던가하는 부분은 실제 정렬 필드를 생성하여 검색을 수행하는 클래스에서 하기 때문에
저 같은 경우는 따로 테스트케이스를 만들어서 사용하고 있습니다.

이 테스트케이스는 정말로 Manager 클래스에 대한 테스트이지요.....


루씬으로 단일 색인 파일로는 15기가정도의 파일까지는 사용을 해보았지만, 다수의 Index 파일은
처음 사용하려 하는 것이고, 개발이 끝난 상태가 아니라서 사실 더 많은 정보를 얻지는 못 하였습니다.

대략적으로 개발이 어느정도 끝나가고 있어서 (주요 모듈들..)
기존에 사용하던 단일 Index 파일로부터 새롭게 사용 할 분석연도별 인덱스 파일을
생성하기 위해 마이그레이션을 진행하였는데 2009년도가 7기가, 2010년도가 12기가 정도
나오는 것 같았습니다. 

이정도면 사용하면서 어느정도 성능이라던가
추가적은 내용에 대한 공부가 될 수 있을 것 같네요...

대략적으로 MultiSearcher의 사용에 대해서 적어보았습니다.

루씬에 처음 다가서시려는 분들께 조금이나마 도움이 되었으면 좋겠네요...

Posted by 용식
이걸 쓴다쓴다 하면서 이제서야 써보네요....

회사에서 간단하게 조회 할 수 있는 프로그램을 만들면서
루씬을 사용하여 데이터를 저장하고 조회 할 수 있도록 하였습니다.

검색어를 분석/통계 내는 프로그램인데
하루 몇십만건의 검색어와 그외 부가적은 데이터들을 색인하여 놓다보니..
이게 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하는 코드를 개발하고
그리고 이를 테스트 할 수 있는 테스트 케이스를
만들어 보도록 하겠습니다.
Posted by 용식