1. 서론

 

색인의 효과와 원리에 대해서는 이제 말했고 본격적인 검색엔진의 차이점을 이야기 하고자 한다.

참고로 오픈소스 검색엔진 (예: solr엘라스틱서치)의 경험은 미비하고, 이전 회사에서 사용하던 독크루저라는 상용검색엔진을 토대로 이야기 할것이다.

 

글을 들어가기에 앞서서 숫자(날짜)의 검색, full scan의 검색에 대해서는 다루지 않음을 밝혀둔다.

그 이유는 너무 일반적이고 이미 알고 있는 내용이기 때문이다.

그래서 DB와 검색엔진에서 큰 차이를 보이는 문자열(텍스트)의 검색과 색인에 대한 이야기를 다루고자 한다.

 



2. 인덱스 다시한번 기억하기 


기억력이 가물가물거리는 독자를 위해 한번 간단히 정리해보겠다.

색인을 한다는건... 색인어와 페이지번호를 추출해서 빠르게 찾게 하는작업이라고 할 수 있다.

열심히 미주알고주알 말해봤자 강아지도 아닌데 "멍~~" 할테니 바로 예를 들어 설명하겠다.


아래와 같이 데이터가 있고 "작성자" 필드를 인덱스로 만들자고 하자.


이때, 색인어를 뽑고, 색인어에 해당하는 순번(ROWID)값을 추출한다. (하단 왼쪽)

이건 개념적으로 그렇다는것이고, 실제로는 탐색속도를 위해 트리로 구성한다. (하단 오른쪽)

(아래 예제로 그린 트리는 개념설명을 위해 발로 그린것이니 밸런싱이나 구성이 이상하다고 따지지말것)

 



Ps. 트리는 insert하면서 밸런싱이 유지될수 있는데, 이런건 아래 링크를 참고하자.

[보조자료] B+트리 삽입과정 (링크)





3. 문자열의 인덱스 사용하기

색인 방법은 색인대상 필드에서 "색인어"를 추출하고, 해당 ROW를 찾아갈수 있는 ROWID를 뽑아내는 과정이다.

(그림에서는 이해를 돕기위해 회색 테이블로 그렸지만, 인덱스는 일반적으로 트리형태로 구성된다)


그리고, 검색하는 방법은 인덱스에 있는 "색인어"를 찾는것이다. (인덱스에서 찾는건 빠르다는걸 2부 1편에 다뤘다)


예를 들어, 작성자 필드에서 '정선생' 을 검색한다고 하면, 인덱스에 있는 색인어에서 '정선생'의 값을 찾으면 된다.

그럼 0번 2번째 행의 값에 데이터가 있음을 알 수 있다.  

즉, 검색 키워드 (=간단히 '검색어' 라고 부르기로 하자) 와 색인어가 같은 데이터를 찾으면 되는것이다.

너무 쉽지 않은가?

 


 

4. 색인어 변경하기


검색은  '검색어'와 '색인어'가 같은것을 찾는 과정이다

그런데 대소문자나 공백이 섞인경우 매칭되지 않아 검색이 안되는 문제가 생긴다.


예를 들어, 아래 테이블에서 제품명이 'IPHONE5 인 데이터를 검색한다고 하면, 검색결과는  0건이다. 

그 이유는 색인어랑 검색어랑 다르기 때문이다. (공백과 대소문자가 다르다)


그런데, 대소문자나 공백 상관 없이 검색할 순 없을까?


정답은?  있다.

방법은?  검색어와 색인어가 같으면 검색되니깐, 검색어와 색인어를 같게 만들어 주면된다.


예를 들어, 공백과 대소문자를 구분없이 검색하고 싶다면, 공백을 없애고 소문자로 변환하는 함수 func()를 만들자.

이 함수는 검색어와 색인어를 같게 만들어 주는 역할을 한다.

색인하기전 func() 를 거친 결과를 색인어로 만든다. 그러면 아래와 같이 iphone5라는 색인어로 인덱스를 만들게 된다. 


 func('iphone5')  ===> iphone5

 func('iphone 5') ===> iphone5 

 func('IPhone 5') ===> iphone5

* 주의 : 원본을 바꾸는게 아니라, 인덱스상의 색인어만 바꾸는것이니 오해하지 말자. 

 

그리고, 검색할때도 색인할때와 동일하게  func()를 거친 검색어 결과를 사용한다.

즉, 'IPHONE5' 으로 검색한다고 하면 아래와 같이 소문자 iphone5로 변경되고 검색을 하게된다.

이 때는, 색인어와 동일해졌기때문에 대소문자나 공백에 영향받지 않고 검색이 가능해진다.


func('IPHONE5') ==> iphon5  

 

참고로 DB에서는 functional-index 라는 기능을 통해 가공한 인덱스를 쓰는것이 가능하다.

독크루저라는 상용검색엔진에서는 공백과 대소문자를 무시하는 string para라는 색인 필드가 존재했다. 

 

색인어 가공하기의 경우는 다음편에 다룰 Stamming 의 아이디어와 유사하므로 알아두자.

 


5. 색인어를 많이 만들기


관계형 데이터베이스에는 필드 하나에는 1개의 값만 존재한기 때문에 이런 색인기술이 필요없었다.

(사실 뻥이다. postgresql같은 경우는 필드에 아예 array형태의 값넣는것도 가능 -링크-)

검색스키마를 구성하다보면 하나의 필드에 여러개의 값이 들어가는 경우가 생긴다.

대표적인 데이터를 말하면 '태그' 를 말 할 수 있다.



별다른 방법이 없이 색인한다면,       "검색,검색엔진,검색프로젝트,색인,인덱스"   라는 하나의 값을 뽑게될것이다. 

이러면, "검색엔진" 이라는 키워드로 검색한다고 하면 like 검색을 할 수 밖에없다.

이럴 경우 좌절단 검색이기 때문에 인덱스를 사용하지 못한다고 이야기 했었다.


그럼 어떻게 하면 인덱스를 사용할 수 있을까? 지금까지는 1개의 필드값은 1개의 색인어를 뽑는것이 원칙아닌 원칙이었다. 하지만, 1개의 값에 N개의 색인어를 뽑으면 해결된다.

예를 들어 콤마(,)를 기준으로 나눠서 색인어를 뽑아서 인덱스를 만들면 like 검색을 하지 않고,

"검색엔진" 이라는 검색어로 인덱스를 사용할 수 있게 된다.

사족으로 말하면 독크루저라는 상용검색엔진에서는 String List라는 필드로 기능을 제공했다.





참고로, 색인어를 많이 만드는 기법은 다음편에 다룰 N-Gram과 형태소분석의 기본 아이디어이니 참고하자.



6. 마치며  


DB에서 생각하는 인덱스와 달리, 색인할때 색인키 자체를 변경하거나 색인키의 후보군을 더 많이 만드는건 인덱스를 활용할 수 없는 상태를 피하기위해 생각할 수 있는 방법들이다.

여기서 나온이야기는 위에 잠깐 언급했지만, 뒤에서 다룰 내용에서 알아야할 필수 아이디어(?)라고 할 수 있다.

또 내용이 길어져버려  형태소분석 Ngram 스태밍 같은 이야기를 다루고 싶었는데, 

결국 또 끊어가게 되는건 조금 아쉽지만, 독자를 한명이라도 이끌기 위해 끊어갈 수 밖에 없다는것을 이해해 주기 바란다.


2부 3편에서는 문장색인 기술들을 다루고자 한다. (형태소분석, Ngram, 스태밍)

사실 형태소 분석도 다루다 보면 엄청 분량이 많지만, 큰 개념을 이해하는것에 촛점을 맞추도록 하겠다.


그럼 다음에 계속....





+ Recent posts