블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 

'search'에 해당되는 글 2

  1. 2017.12.29 NMF 알고리즘을 이용한 유사 문서 검색과 구현(2/2) (3)
  2. 2012.02.21 NoSQL Riak Overview #1/2
 

NMF 알고리즘을 이용한 유사 문서 검색과 구현(2/2)

sklearn을 이용한 구현


조대협 (http://bcho.tistory.com)


http://bcho.tistory.com/1216 를 통하여 tf-idf를 이용하여 문서를 벡터화 하고, nmf를 이용하여 문서의 특성을 추출한 다음, 코싸인 유사도를 이용하여 유사 문서를 검색하는 알고리즘에 대해서 알아보았다. 이번글에서는 이 알고리즘을 직접 sklearn을 이용해서 구현해보도록 하자. sklearn은 이용하면 분산 학습을 이용한 대규모 데이타 처리는 불가능하지만, 작은 수의 문서나 모델에는 사용이 가능하다. 무엇보다 sklearn의 경우 대부분의 모델을 라이브러리화 해놓았기 때문에, 복잡한 구현이 없이 쉽게 사용이 가능하다.


전체 소스 코드는 https://github.com/bwcho75/dataanalyticsandML/blob/master/NMF%20based%20document%20recommendation/NMF%20based%20similar%20document%20recommendation.ipynb 에 공유되어 있다.


샘플 데이타

여기서 사용할 데이타 셋은 sklearn 테스트 데이타셋에 있는 20개의 뉴스 그룹의 이메일 데이타를 사용한다. 총 20개의 토픽으로 약 18000개의 포스팅으로 구성되어 있다.


이메일 텍스트 형식으로, 제목과, 날짜등의 헤더 정보와 이메일 내용으로 구성되어 있다. 첫번째 코드에서는 이 데이타를 읽어서 제목과 본문만을 추출하여, Pandas data frame에 저장하도록 한다.


from sklearn.datasets import fetch_20newsgroups
import StringIO
import pandas as pd

newsgroups_train = fetch_20newsgroups(subset='train')

def parseDocument(data):
   buf = StringIO.StringIO(data)
   line=buf.readline()
   data=[]
   subject=''
   while line:
       if(line.startswith('Subject:')):
           subject = line[8:].strip()
       elif (line.startswith('Lines:')):
              lines = line[6:]
              while line :
                   line = buf.readline()
                   data.append(line)
       line=buf.readline()
   text = ''.join(data)
   
   return subject,text


textlist = []
df = pd.DataFrame(columns=['text'])
for data in newsgroups_train.data[0:1000]:
   subject,text = parseDocument(data)
   df.loc[subject]=text
df.head()


제목은 ‘Subject:’로 시작하는 줄에 들어 있고, 본문은 ‘Lines:’로 시작하는 줄에 있다. 이 내용들만을 추출하여 pandas data frame에 저장하였다. 본문은 data frame 상에 ‘text’라는 이름으로된 컬럼에 저장하였다.

Tfidf 를 이용한 단어의 벡터화 구현

단어를 벡터로 변환하기 위해서 앞에서 설명한 tfidf 모델을 이용한다. sklearn에 이미 구현이 되어 있기 때문에 어렵지 않게 구현이 가능하다.


from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer()
vectors = vectorizer.fit_transform(df['text'].tolist())
print(vectors.shape)


간단하게, TfidfVectorizer를 로딩한다음에, fit_transform을 이용하여, 문장의 본문이 있는 데이타 프레임의 ‘text’ 컬럼을 배열 형태로 변환하여 리턴해주면 된다.


NMF를 이용하여 본문에서 특성 추출

문서가 tf-idf를 이용하여 벡터화가 되었으면, NMF를 이용하여, 각 문서별로 특성을 추출한다.

NMF역시 sklearn에 NMF라는 모듈로 미리 정의되어 있다. 단지, 몇개의 특징으로 압축을 해낼것인지만 지정하면 되는데, 여기서는 n_components 인자를 이용하여 총 40개의 특징으로 특성을 압축하여 추출하도록 하였다.


from sklearn.decomposition import NMF

vector_array = vectors.toarray()
nmf = NMF(n_components=40)
nmf.fit(vector_array)
features = nmf.transform(vector_array)


추출된 피쳐는 features 변수에 저장하였다.

피쳐 정규화

추출된 피쳐가 피쳐마다 또는 문서마다 변화의 폭이 클 수 있기 때문에, Normalizer를 이용하여 0~1사이로 스케일링을 한다. 이 정규화 역시 간단하게 아래와 같이 Normalizer 모듈을 이용하면 된다.


from sklearn.preprocessing import Normalizer

normalizer = Normalizer()
norm_features=normalizer.fit_transform(features)

print(norm_features[0:2])


정규화된 피쳐가 배열 형태이기 때문에, 사용 편의상 데이타 프레임에 로딩한다.


df_features = pd.DataFrame(norm_features,index=df.index.tolist())


df_features 변수에 문서별 특징과 문서 제목을 가지고 데이타 프레임을 만들어서 생성하였다.

인덱스는 문서의 이름이 될것이고 0~39 컬럼은 각문서별 특징이 된다. 출력해보면 대략 다음과 같은 모양이 된다.


문서 유사도 계산

문서별로 특징을 계산이 끝났으면 특정 문서와 유사한 문서를 찾도록 해보자.

앞의 글에서도 설명했지만, 문서의 유사도는 코싸인 유사도를 사용한다.

공식을 다시 기억해보면


여기서 A는 문서 A의 특성 행렬, B는 B 의 특성 행렬이 된다. |A|와 |B|는 각 문서 특성 행렬의 벡터의 길이인데, 앞에서 정규화 Normalization 을 하면서 각 문서의 행렬의 크기가 1이 되었기 때문에, 여기서 코싸인 유사도는 A*B / |A|*|B| = A*B / 1*1 = A*B 가된다.

즉 두 문서의 특성 행렬을 곱한 값이 코싸인 유사도가 된다.


데이타 프레임을 이용하면, 하나의 문서 특성 행렬을 전체 문서에 대해서 곱할 수 있다. .dot 함수를 이용하면 되는데,


article = df_features.loc['WHAT car is this!?']


“WHAT car is this!?” 라는 문서의 유사한 문서를 찾아보도록 하자. df_features에서 “WHAT car is this!?” 의 특성 행렬을 찾아내서 article 변수에 저장하고


similarities=df_features.dot(article)


전체 문서의 특성행렬에서 각 문서의 특성 행렬과 article 문서의 특성행렬을 곱한다. 그러면 article 문서에 대해서 각문서에 대한 유사도가 계산이된다.


top=similarities.nlargest()


이 값을 큰 순서대로 소팅해서 top 이라는 변수에 저장해놓고, 유사도가 높은 문서데로 문서의 제목과 유사도를 출력해본다.


texts = df.loc[top.index]['text'].tolist()
i = 0
for text in texts:
   print('TITLE :'+top.index[i]+" Similarities:"+ str(top[i]))
   #print(text+'\n')
   i = i+1



다음은 실행 결과이다.

TITLE :WHAT car is this!? Similarities:1.0
TITLE :Re: WHAT car is this!? Similarities:0.999080385281
TITLE :Re: New break pads & exhausts after 96K km (60K mi) on '90 Maxima? Similarities:0.980421814633
TITLE :Insurance Rates on Performance Cars SUMMARY Similarities:0.945184088039
TITLE :Re: What is " Volvo " ? Similarities:0.935911211878


간단하게 tf-idf와 NMF를 이용한 문서 유사도 측정을 구현해봤다. 조금 더 높은 정확도와 대규모 학습을 위해서는 이보다는 Word2Vector를 이용한 문서의 벡터화와, 딥러닝을 이용한 문서의 유사도 분석을 하면 훨씬 정확도를 높일 수 있다. 전체 기본 개념은 유사하다고 보면 된다.


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. 2018.04.01 18:58  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  2. DongKo 2018.11.04 20:51  댓글주소  수정/삭제  댓글쓰기

    좋은 글 너무 감사합니다

  3. 2019.02.22 10:18  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

NoSQL Riak Overview #1/2

클라우드 컴퓨팅 & NoSQL/Riak | 2012.02.21 18:21 | Posted by 조대협

Riak 계보

Riak은 이미들 잘 알고 있는 NoSQL 데이타 베이스이다. Basho.com이라는 회사에서 만들어서 배포하고 있고, 무료 버전인 Community version과 상용 기술 지원을 받을 수 있는 Enterprise version을 지원하고 있다.

NoSQL 계보는 크게 두 가지로 나눠지는데,  Google Big Table 논문을 기반으로 한 HBase,HyperTable 등과, Amazon Dynamo 논문을 기본으로 한 Cassandra등의 계열로 나뉘어 지며, Riak Dynamo 계열에 속한다.

데이타 모델에 있어서는 Key,Value 저장형식을 취하는데, Value JSON 문서가 저장되는 문서 저장형 데이타 베이스 형식을 취하며, 이는 MongoDB CouchDB와 유사한 데이타 모델을 갖는다.

이런 특성 때문인지, MongoDB로 부터 Migration되는 사용자가 많은 것으로 알려져 있다.

Riak의 기술적인 특징

Ring 구조 기반의 아키텍쳐

Riak은 앞에서 언급했듯이, Dynamo 계열의 구조를 가지기 때문에 데이타를 분산 저장 시키는 구조에 있어서 Ring 구조를 갖는다. Hash 알고리즘에 의해서, 데이타 Key에 따라서, 적정 노드를 찾아가는 구조로 되어 있다.


Riak의 클러스터링 단위는 크게 node vnode로 나눌 수 있는데, node는 물리적인 서버를 지칭하며, vnode는 논리적인 서버로 하나의 인스턴스 개념정도로 생각하면 된다. 하나의 물리서버에는 여러개의 논리서버 (vnode)를 설치할 수 있다.

Riak은 이 Ring 구조를 Runtime 시에도 동적으로 재 설정할 수 있다. (node를 추가하거나 뺄 수 있다. )이 과정에서 Riak이 자동적으로 데이타를 변형된 Ring 구조에 따라서 재배포 한다.

마스터 노드가 없는 아키텍쳐

Mongodb등은 데이타를 저장하는 노드와, Request를 라우팅하는 (mongos,mongod)로 구성된다. master-slave 개념이 있는 아키텍쳐인데 반해서, Riak은 별도의 마스터 노드를 가지지 않는다. 이 말은 Single Failure Point (단일 장애 지점)이 없다는 것을 의미한다. 각 노드로의 로드밸런싱은 앞단에 L4 스위치를 넣거나 Apache NginX와 같은 웹서버를 이용하여 소프트웨어 로드밸런서(Reverse Proxy)를 사용하여 구성할 수 있다.

※ 앞단의 로드밸런서는 Riak vnode의 장애상태를 판단할 수 없기 때문에, Riak에서 제공되는 Client SDK를 사용하면, 신속한 장애 감지가 가능하며, 이에 더하여 Connection Pooling등을 이용하여 성능 향상과 자원 사용의 효율성을 높일 수 있다.

데이타 복제 (Replication)

NoSQL 답게 내부적으로 데이타를 복제하는 구조를 가지고 있다. 몇개의 데이타를 복제하느냐를 “N-Value”라고 하는데, 일반적으로 디폴트 설정이 3개의 복사본을 가지는 것을 정책으로 한다.

일반적으로 근래에 나오는 분산 저장 시스템은 3개의 복사본을 가지는 것이 유행인데, 3개를 갖는 이유는 1개의 데이타 본에 대해서 작업을 진행하고 있을때, (확장이나 삭제) 장애가 났을때를 대비해서 2개의 노드가 Active상태인 것을 유지하기 위함이다.

당연히 노드간의 데이타 복제가 이루어 지는데, 이 데이타 복제는 실시간으로 이루어지는 것이 아니기 때문에 데이타의 consistency가 정확하게는 보장되지 않는다. 즉 데이타를 WRITE하고나서, 다른 노드에서 READ를 할 경우 복제가 이루어지기 전에 READ하면 예전 데이타가 READ될 수 있다는 의미이다. (millisecond 단위이기는 하지만)

CAP 이론

CAP 이론은 2002년 버클리 대학의 Eric Brewer 교수에 의해서 발표된 분산 컴퓨팅 이론으로, 분산 컴퓨팅 환경은 Consistency, Availability, Partitioning 3가지 특징을 가지고 있으며, 이중 두가지만 만족할 수 있다는 이론이다.


    Consistency는 분산된 노드중 어느 노드로 접근하더라도, 데이타 값이 같아야 한다는 기능적 특징이다. (데이타 복제 중에 Query가 되면, Consistency를 제공하지 않는 시스템의 경우 다른 데이타 값이 Query 될 수 있다)

    Availability는 클러스터링된 노드중, 하나 이상의 노드가 FAIL이 되더라도, 정상적으로 요청을 처리할 수 있는 기능을 제공하는 특징이다.

    Partition Tolerance는 클러스터링 노드간에 통신하는 네트워크가 장애가 나더라도 정상적으로 서비스를 수행할 수 있는 기능이다.

 

Riak은 이중에서 A P를 지원하는 방향으로 구현되어 있다..

Riak의 데이타 구조

Bucket

Bucket RDBMS database로 보면 된다. 일종의 컨테이너로 여러개의 keyspace (RDBMS로 치면 table)를 담고 있으며, Bucket 마다 Property로 특성을 정의할 수 있다. (복제되는 Replica의 수나, 실제 저장되는 물리 스토리지 타입등)

Data Structure

Riak은 다른 NoSQL과 유사하게 Key-Value 형태의 저장 구조를 갖는다. (Hash Table을 생각하면 쉽게 이해할 수 있을 듯). Key는 해당 Bucket에서 Unique해야 하며, Value JSON Document 또는 Binary 데이타를 저장할 수 있다. 특이 사항은 데이타 구조에 Header 부분을 포함하고 있는데, Header는 사용자가 정의하는 메타데이타나 또는 Riak에서 제공하는 Index 지정, Object와의 Link 관계등을 정의한다.

 

Riak Architecture

지금까지 Riak의 일반적인 특성에 대해서 알아보았다. 조금 더 깊게 들어가서 Riak의 아키텍쳐 및 몇몇 기술적인 특징에 대해서 살펴보도록 한다.


<그림 Riak Architecture Stack>

Storage BackEnd

Riak은 데이타를 저장할 때, 물리적인 저장소를 선택할 수 있는데, 다음과 같이 크게 4가지 저장소 타입을 지원한다.


BitCask

Bitcask Basho에서 만든 스토리지로, Erlang을 베이스로 한다.
Key Index
를 메모리에 올리기 때문에 빠른 성능을 제공하지만 반대로, 다른 스토리지 백엔드에 비해서 많은 메모리를 필요로 한다
.
Bitcask
append only 데이타베이스로, 데이타에 대한 삭제나 변경이 불가능하기 때문에, 데이타의 삭제 변경이 일어나면 새로운 버전을 저장하고 History를 관리하는 형태를 취한다. 이 때문에, 예전 버전을 주기적으로 삭제하는 Garbage Collection 작업을 수행한다.

InnoStore

Innostore Oracle InnoDB Wrapping한 스토리지로 대용량 저장에 강점이 있다고 한다. InnoDB, 이미 MySQL Backend로도 검증이 된 만큼 신뢰성도 높고, Oracle쪽으로 부터 Commercial Support도 받을 수 있으니, 안정성 측면에서 조금 더 높은 보장이 가능하지 않을까 하는 개인적인 생각이다.

InnoStore는 기본적으로 Riak에서 그리 추천하지는 않으나, BitCask의 경우는 메모리를 많이 필요로 하는 반면 InnoStore는 메모리를 많이 필요로 하지 않기 때문에 이런 시나리오에서 사용이 가능하다. InnoStore 설계시 주의점중의 하나는 InnoDB DB 파일과 Log 파일을 별도의 Disk에 나눠서 저장해야 제 성능을 발휘 할 수 있다.

LevelDB

LevelDB Google에서 얼마전에 발표한 DB, BigTable 이론에 근간을 두고 구현되었다.

마지막으로 Memory가 있는데, Memory는 현재 문서상으로 봤을때는 테스트등의 용도로 주로 사용이 되며, Redis Memcached와 같은 메모리 캐쉬 용도로도 사용이 가능하리라 판단된다. (주관적인 생각)

Riak에서는 용도와 목적에 따라서 이 4가지 Storage BackEnd를 하나의 Riak Cluster에서 혼합하여 사용할 수 있도록 한다.

문서상에는 4개의 Storage BackEnd에 대한 특징이나 선택 방법에 대해서 명확한 가이드를 주고 있지는 않으며, Default로는 BitCask를 추천하고 있으며, Secondary Index를 사용하고자 할때는 BitCask + LevelDB를 추천하고 있다.

Riak KV

Riak KV Key Value Storage, Riak의 메인 데이타 저장 구조를 담당하는 부분이다. Key : Value Pair로 데이타를 저장한다. 데이타를 Query하는 면에서 두 가지 방식을 지원하는데, Secondary Index MR (Map & Reduce)를 지원한다.

Map & Reduce

MR은 데이타 검색에 관련된 작업을 여러개의 vnode로 나눠서 작업을 한후 (Map), 결과를 합쳐서 리턴해주는 형태(Reduce)를 사용한다. MR을 사용할때, Map Function Reduce Function을 정의해서 request에 함께 보내는데, Map Reduce Function Erlang 또는 JavaScript 기반으로 작성이 가능하다.

(참고 : Riak MR - http://wiki.basho.com/MapReduce.html)

Map 예제) 데이타에서 “High” 필드가 600 이상인 값을 찾는 Map Function (JavaScript 버전)

Function(value, keyData, arg) {

  var data = Riak.mapValuesJson(value)[0];

  if(data.High && data.High > 600.00)

    return [value.key];

  else

    return [];

}

실제로 Riak에 호출할때는 REST+JSON을 이용하여 HTTP Request를 다음과 같이 보낸다.

{"inputs":"goog",

 "query":[{"map":{"language":"javascript",

                  "source":"function(value, keyData, arg) { var data = Riak.mapValuesJson(value)[0]; if(data.High && parseFloat(data.High) > 600.00) return [value.key]; else return [];}",

                  "keep":true}}]

}

 

Map & Reduce 예제) 다음 예제는 Map Reduce를 포함한 예제이다.
Map
을 이용하여, 매월별 매출의 편차(최고-최소:data.High-data.Low)를 계산하고, Reduce 단계에서 매월 매출 편차가 가장 큰 값을 찾는 예제이다.

/* Map function to compute the daily variance and key it by the month */

function(value, keyData, arg){

  var data = Riak.mapValuesJson(value)[0];

  var month = value.key.split('-').slice(0,2).join('-');

  var obj = {};

  obj[month] = data.High - data.Low;

  return [ obj ];

}

 

/* Reduce function to find the maximum variance per month */

function(values, arg){

  return [ values.reduce(function(acc, item){

             for(var month in item){

                 if(acc[month]) { acc[month] = (acc[month] < item[month]) ? item[month] : acc[month]; }

                 else { acc[month] = item[month]; }

             }

             return acc;

            })

         ];

}

 

Secondary Index

이번 릴리즈에서 Riak의 새로운 강력한 기능 중에 하나가 Secondary Index를 지원하는 기능이다. 쉽게 이야기 하면, RDB로치자면 Primary Key 뿐만 아니라, 테이블 상에 여러개의 Column Index를 걸어서 특정 Record Query할때 빠른 응답 시간을 보장한다. (Riak은 하나의 KeyStore에 여러개의 Index를 동시에 걸 수 있다.)

Riak에서 Index를 정의하는 방법은 REST PUT/POST 메서드를 이용해서 데이타를 입력하거나 수정할때, 헤더 부분에 “x-riak-index-{인덱스명}_{데이타타입}:{인덱스 데이트} 형식으로기술 한다. 다음은 user 라는 Key Value Store“twitter”“email”이라는 필드를 인덱스로 지정하는 예제이다.

curl -X POST \

-H 'x-riak-index-twitter_bin: rustyio' \

-H 'x-riak-index-email_bin: rusty@basho.com' \

-d '...user data...' \

http://localhost:8098/buckets/users/keys/rustyk

 

Index를 이용해서 데이타를 쿼리 하는 방법은 HTTP GET /{버킷명}/index/{인덱스명}/{인덱스값} 으로 서술하면 된다. 아래는 “users”라는 버킷에서 “twitter_bin” index에서 “rustyio”라는 값을 가지는 Object를 쿼리 해오는 예제이다.

localhost:8098/buckets/users/index/twitter_bin/rustyio

2012 2월 현재 Riak Secondary Index는 몇 가지 제약사항을 가지고 있다. 먼저 여러개의 Index를 동시에 사용하여 검색을 할 수 없으며, 검색 결과에 대한 Sorting이나 Paging은 지원되지 않는다. (Range Search는 가능-예를 들어 나이가 20~30세 사이를 갖는 Object에 대해서 Index를 가지고 검색 가능)

Index 정보는 파일 형태로 Object가 저장되는 동일한 vnode에 저장되며, Index 정보는 내부적으로 Google LevelDB storage backend에 저장된다. Key/Value의 경우 Ring Topology를 기본으로 Key값에 대해서 Hash 값을 기반으로 특징 vnode를 찾아가기 때문에, 그 특정 vnode request를 받는데 반해서, Index 기반의 Query의 경우, Index 값이 어느 vnode에 저장되었는지 찾을 수 가 없다. (앞서 설명하였듯이, Object에 대한 Index Object가 저장된 동일한 vnode에 저장이 되기 때문에, Index값을 기반으로 Hash 등의 검색이 불가능 하다. ) 이런 이유로 index Query를 수행하게 되면 전체 vnode Query가 분산 되서 수행되기 때문에, Index 기반의 Query는 전체 노드에 부담을 준다. (1/N vnode에서 수행됨)

Riak Search

Riak Search Value의 내용을 가지고 검색을 가능하게 해주는 Full Text Search (FTS) 기능이다. Riak Search Apache FTS Lucene (http://lucene.apache.org)을 기본으로 구현되었고, Riak Erlang으로 구현되어 있고 원래 Lucene Java로 구현되어 있기 때문에 Riak에 최적화하기 위해서 Lucene의 일부를 Erlang으로 재구현하였다.

 설명에 앞서서 앞에 아키텍쳐 다이어그램에서는 Riak Search Riak KV와 분리해서 표현하였지만, 물리적으로 Riak Search Riak KV의 일부이다. (KV를 설치하면 안에 Search가 들어가 있다.) 이는 Riak의 디자인 사상과도 결부되는데, Search를 별도의 모듈로 분리하지 않고 합침으로써 운영에서 많은 컴포넌트를 관리해야 하는 부담을 덜어준다.

먼저 Search에 대해서 이해하기 이해서 Search 가 어떻게 Search Index를 저장하는지를 이해할 필요가 있다. Riak Search Index 저장 방식은 “Term Partitioning” 이라는 기법을 사용한다. Key/Value안에 있는 Value Text Parsing Term 단위로 나눈다. 이때 Term 단위로 잘라내는 것을 Analyzer가 담당하는데, 단순하게 탭이나 스페이스 단위로 잘라서 Term을 추출할 수 도 있고, 아니면 검색 Dictionary 기반을 사용하는 등 여러가지 방법을 사용할 수 있으며, 사용자 요구 사항에 따라서 직접 Analyzer를 제작할 수 도 있다.
http://wiki.basho.com/Riak-Search---Indexing.html

Term이 추출이 되면 이 Term Index로 사용하는데, Term을 전체 Cluster에 걸쳐서 분산해서 저장한다. Key-Value 저장 방식과 거의 동일한 방식으로 나눠서 저장하며 N-Value에 따라서 복제본 역시 같은 형태로 저장한다.

이렇게 Term Partitioning을 사용함으로써, Query시에 Search Keyword가 들어오면 단일 단어의 경우 어느 vnode에 저장되는지 Hash값을 통해서 찾을 수 있기 때문에, 전체 노드에 걸쳐서 Search 연산이 일어나지 않는다. (Secondary Index와 비교되는 부분). wild card 문자를 사용하거나 AND,OR등의 기타 연산문을 사용할 경우 경우에 따라 1~1/N개의 vnode에 걸쳐서 Query가 분산되어 수행될 수 있다.

Map & Reduce, Secondary Index, Search 비교

 

MapReduce

Riak Search

Secondary Indexs

Query Types

Map Reduce Function을 이용하여 쿼리 구현

Lucene SOLR 쿼리를 사용하여, 텍스트 검색, wildcard 모델과 Boolean 검색(AND,OR) 사용

동일값 비교(Equality), 범위 기반의 쿼리(Range Query)지원

Index Locality

N/A

Search Index N개의 vnode에 분산되어 저장됨 Riak KV와 동일한 백앤드를 사용

Object가 저장된 동일한 vnode Index가 저장됨
Data Storage Backend
LevelDB를 사용함

Vnodes Queried

Depends on input

Map & Reduce 로직에 따라서 Query가 수행되는 vnode가 결정됨

1 per term queries; 1/N for trailing wild card

하나의 “Term”으로 검색할 경우, “Term Index”가 저장된 vNode에서 수행됨.

Wildcard 검색을 할 경우 전체(1/N) vNode에 걸쳐서 수행됨

1/N per request (aka coverage query)

전체(1/N) vnode에 걸쳐서 분산 수행됨

Supported Data Types

Map Reduce를 위해서 Erlang JavaScript 사용, JSON 사용

Integer, Date and Text

Binary and Integer

Suggested Use Cases

 

Value 내의 Full Text Search

Tag 기반 검색

Poor Use Cases

많은 수의 Object에서 복잡한 연산을 하는 케이스

Searching for common terms in documents

 

Limitation

 

 

Backend Storage LevelDB 를 사용해야함

동시에 여러개의 Index를 사용하는 Query는 불가능함

Anti-Entropy Fault Tolerance

 

 

 

Extraction

 

 

 

 

'클라우드 컴퓨팅 & NoSQL > Riak' 카테고리의 다른 글

Riak 장점 다시 정리  (2) 2012.03.12
Riak Performance  (0) 2012.03.12
Riak vs CouchDB  (0) 2012.03.12
NoSQL Riak Overview #1/2  (0) 2012.02.21
Riak관련 스터디 메모  (0) 2012.02.21
Riak Quick Review  (0) 2011.12.19
본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요