대용량 시스템을 위한 데이타베이스 아키텍쳐
Sharding & Query Off Loading

RDBMS는 크게 request를 바로 처리하는 트렌젝션 처리용의 OLTP(On-Line Transaction Processing)성과, 데이타를 모아서 분석하고 리포팅하는 OLAP(On-Line Analytical Processing) 두가지로 분리된다. 여기서 설명하는 RDBMS는 OLTP성의 데이타 베이스 이다.

RDBMS는 2차원 테이블 구조의 데이타를 KEY 값을 중심으로 여러개의 컬럼으로 저장되며, 저장된 각각의 로우(행)은 다른 테이블의 로우와 관계를 가질 수 있다.

RDBMS를 이용한 설계를 하는데, 고려할만한 아키텍쳐는 성능 향상을 위한 Query Off Loading과, Sharding이라는 기법이 있다.


Query Off Loading

 Query Off Loading은 DB의 성능 향상을 위한 기법이다. (정확하게 이야기 하면, 처리량을 증가 시키기 위한 설계 기법이다.) DB 트렌젝션의 70~90%는 대부분 READ 성이 많다. 나머지 10~30%가Create/Delete/Update와 같은 트렌젝션인데, 이 Update 성 트렌젝션과 Read 트렌젝션을 분리하는 기법이다.



먼저 Master DB에는 쓰기(Update)만을 허용하고, Master DB의 내용을 중간의 Staging DB라는 곳으로 복사한다. 이 Staging DB는 복제된 내용은 N개의 Slave DB로 복제한다.

애플리케이션은 Master DB에만 쓰기를 하고, 읽기는 Slave DB에서만 수행한다. 이를 위해서Application을 DB에 대한 쓰기 로직과 읽기 로직을 분리해서 구현해야 하며, 이 분리된 로직은 쓰기DB로 접근하기 위한 DB Connection과 읽기 DB로 접근하기 위한 DB Connection을 이용해서 접근한다. 일반적으로 application server에서는 이러한 Connection을 Connection Pool 을 이용해서 관리 하는데, 읽기 DB의 경우에는 N개의 Slave DB로 부터 읽기 때문에, Application이 이 N개의 Slave DB에 대한 요청을 Load Balacing을 해야 한다. 또한 특정 Slave DB 장애시 다른 Slave DB 인스턴스에 접근을 할 수 있도록 HA (High Availability) 기능을 제공해야 하는데 Connection Pool 자체에 Load Balancing과 HA 기능을 가지고 있는 Connection Pool을 이용하거나 또는 JDBC Driver와 같이DBMS용 Driver 자체에 Load Balancing과 HA 기능을 사용한다.

Master DB와 Slave DB는 각각 쓰기와 읽기를 위해서 접근된다고 하지만 그렇다면 중간에 Staging DB의 역할은 무엇일까? Staging DB는 Slave DB로 복제하기 위한 중간 경유지 역할을 한다. 다수의Slave DB로 복제를 해야 하기 때문에, 이에 대한 부하가 크다. 만약 Master DB에서 Slave DB로 바로 복제를 하게 되면, Master DB가 쓰기 트렌젝션 이외에 복제에 대한 부분을 처리해야 하기 때문에 성능 저하를 유발할 수 있다. 이를 방지 하기 위해서 중간에 Staging DB를 넣는 것이다.

그렇다면 Master à Staging à Slave DB로의 복제는 어떤 기술을 이용할까?

CDC (Change Data Capture)라는 기술을 이용한다. DBMS들은 공통적으로Create/Update/Delete와 같은 쓰기 관련 작업을 수행할때, 데이타를 실제로 저장하기 전에 먼저 해당 작업에 대한 request를 BackLog라는 곳에 저장한다. (BackLog는 일반적으로 Local 파일이다.) 이는 실제로 데이타를 쓰기전에 장애가 났을때, restart하면서 이 BackLog를 읽어서 복구를 위한 용도로 사용이 된다. CDC는 이 Back Log를 이용해서 데이타를 복제하는데, Source DB로 부터 이 Back Log를 읽어서, 복제를 하고자하는 Target DB에 replay 하는 형식이다.

즉 Source DB에서, insert A,B,C를 하면 이는 모두 Back Log에 기록되고, 이를 읽어서 Target DB에서 다시 replay – insert A,B,C를 순차적으로 수행하는 것이다.

대표적인 CDC 제품으로는 Oracle의 Golden Gate, Quest의 Share Flex가 있고, 오픈소스 제품으로는Galera[1]라는 제품이 있다.


Sharding

Sharding은 데이타베이스의 용량 한계를 극복하기 위한 기술이다. 클러스터링 기술을 사용하더라도 데이타 베이스는 물리적인 용량 한계를 갖는 경우가 많다. 수년 전에만 해도, 하나의 서비스에 수천만명이 사용하는 서비스는 없었다. 인터넷의 발전등에 따라서 사용자가 급격하게 늘어나고 저장해야 하는 데이타의 양도 급격하게 늘어났다. 데이타 베이스 시스템은 이러한 용량 증가를 따라가지 못했다. 그래서Sharding이라는 아키텍쳐가 유행하기 시작했는데, Sharding은 쉽게 말해서 데이타를 여러개의 데이타 베이스에 나눠 담는 방법이다.

하나의 데이타 베이스가 10억개의 레코드만 저장할 수 있다면, 100억개의 데이타를 저장하려면 10개의 데이타 베이스를 사용하여 분산 저장하는 방법이다. 이 각 10개의 데이타 베이스를 Shard라고 한다.

Sharding은 데이타를 분산 하는 방식에 따라서 Vertical(수직적) Sharding과 Horizontal(수평적) Sharding으로 나뉘어 진다.

Vertical Sharding은 연속된 데이타에 대해서 범위별로 데이타를 나누는 방법이다. 아래 예는 연령대 별로, 데이타를 나누는 예이다.



Figure 1 Vertical Sharding


다음으로는 Horizontal Sharding이 있는데, 이는 연속된 키가 아니라 “Category”와 같은 종류에 따라서 데이타를 수평적으로 분리하는 방법이다.



Figure 2 Horizontal Sharding


데이타를 분산 저장할때 위와 같이 meaningful한 데이타를 사용할 수 있는데, 이 경우에는 데이타의 몰림 현상이라는 것이 발생할 수 있다. 위의 Vertical Sharding을 예를 들어보면, 해당 서비스를 사용하는 연령층이 20대와 30대에 편중되어 있다면, 20,30대 Shard에는 데이타가 몰리게 되고, 부하도 더 많이 받게 될 것이다. 그래서 이렇게 meaningful한 데이타를 KEY로 사용할 경우에는 데이타 몰림현상을 고려하여 각 Shard 서버의 성능을 비 대칭적으로 설계할 수 있다. 즉 20,30대의 Shard에는 더 좋은 CPU와 메모리를 갖는 서버를 배치하는 방법이 대안이 된다.

만약에 데이타 편중 현상에 대한 예측이 어려운 경우에는, meaningful 하지 않은 KEY를 사용해서Sharding을 할 수 있다. 10개의 Shard를 갖는 데이타 베이스에서, 사용자 레코드를 등록할때, KEY를Sequence를 이용해서 순차적으로 부여한다. 첫번째 사용자는 1, 두번째는 2, 다음은 3,4,5,6.. 등으로.. 그리고 이 ID를 10으로 나눈 나머지 값을 가지고 Shard를 결정하면, 데이타를 모든 Shard에 걸쳐서 골고루 분산 시켜 배치 할 수 있다. (Hash 방식)

Sharding을 구현하는 방법은 DBMS 단에서 Sharding을 지원 하는 방법과, OR Mapper와 같은 DB 접근용 프레임웍에서 Sharding을 제공하는 방법 그리고, Application Code 자체에서 지원하는 방법 세가지가 있다.

DBMS 단에서 제공하는 방법으로는 Microsoft SQL Server Azure의 federation model[2]이나RDBMS는 아니지만 NoSQL중 MogoDB의 경우 1.6부터 Sharding을 DB단에서 지원한다.

프레임웍단에서는 자바의 Hibernate의 경우 Hibernate Shard[3]라는 기능을 통해서 Sharding을 지원한다.  프로그래밍 언어인 Grail의 경우에도 자체 프레임웍에서 “Grails Sharding Plug in”을 통한Sharding 을 지원한다.

직접 Application에서 구현할 경우 Key에 따라서 DB Instance를 선택적으로 고를 수 있는 구조를 가져야 하며, 특히 다른 Shard간의 데이타 Join등은 불가능하기 때문에, 구현상에 이에 대한 고려가 필요하다.

Sharding 이라는 것이 데이타를 분산 저장함으로써 시스템의 전체 용량을 늘릴 수 는 있지만Application의 복잡도가 올라가고, 데이타 편중 방지등 여러가지 요소를 고려한후에 설계, 반영해야 한다..


출처 - http://bcho.tistory.com/670





'DB > Common' 카테고리의 다른 글

db - jdbc vs jpa  (0) 2013.09.14
db - ACID  (0) 2013.06.22
SELECT문 순서와 처리순서  (0) 2012.08.29
데이터 입력과 db insert 사이에 버퍼링 방법  (0) 2012.07.13
dbms - join  (0) 2012.07.06
Posted by linuxism
,


NoSQL 데이타 모델링 #1

Facebook Server Side Architecture Group
http://www.facebook.com/groups/serverside
조대협

빅데이타,클라우드,NoSQL은 요즘 기술적인 화두중에 하나이다. 그중에서도 NoSQL은 많은 사람이 관심을 갖고 있음에도 불구하고, 기존의 RDBMS 데이타 모델링 관점에서 접근을 하기 때문에, 많은 문제를 유발한다. NoSQL은 데이타 베이스이기도 하지만 RDBMS와는 전혀 다른 성격을 가지고 있고, 접근 방식도 틀리다.

특히 테이블 구조를 정의 하는 데이타 모델에 따라서 NoSQL의 성능은 하늘과 땅차이만큼 차이가 난다. 이 글에서는 NoSQL의 데이타 모델링 기법에 대해서 소개하고자 한다.
※ 깨지는 그림은 클릭해서 봐주세요.

NoSQL 데이타 모델

데이타 모델링에 앞서서 NoSQL이 어떤 구조로 데이타를 저장하는지를 먼저 이해할 필요가 있다. NoSQL의 데이타 모델링 패턴은 아래와 같이 크게 3가지 패턴정도로 구분된다.

1.     Key/Value Store

가장 기본적인 패턴으로, 대부분의 NoSQL은 다른 데이타 모델을 지원하더라도, 기본적으로Key/Value의 개념을 지원한다. Key/Value Store란, Unique한 Key에 하나의 Value를 가지고 있는 형태를 이야기 한다. Put(Key,Value), Value := get(Key) 형태의 API로 접근한다.


Value는 String이나 Integer와 같은 Primitive 타입이 될 수 도 있지만, 이정도로는 우리가 일반적으로 사용하는 테이블 형태의 데이타를 저장할 수 없기 때문에, 조금 더 확장된 개념을 사용하는데, Column Family라는 개념을 사용한다. Key 안에 (Column,Value) 조합으로 된 여러개의 필드를 갖는데, 이를 Column Family라고 한다.


예를 들어, 사용자 프로필을 저장하는 시나리오가 있을 때, 사용자의 이름을 KEY로 한다면, 성별,주소,나이들은 각각의 Column이 될 수 있다. Key 필드는 RDBMS에서 Primary Key, Column 필드들은 RDBMS의 일반 데이타 필드로 이해하면 된다. 프로그램 언어와 비교해서 생각한다면, Key/Value Store는 Map 데이타 구조와 유사하다.
Oracle Coherence나 Redis와 같은 NoSQL이 이 데이타 모델을 기본 모델로 사용한다.

2.     Ordered Key/Value Store

Key/Value Store의 확장된 형태로 Key/Value Store와 데이타 저장 방식은 동일하나, 데이타가 내부적으로 Key를 순서로 Sorting되서 저장된다.



Sorting이 별거 아닌것 같지만, NoSQL 관점에서는 대단히 중요한 기능을 제공하게 된다. 뒤에 데이타 모델링 기법에서도 다루겠지만, NoSQL은 RDBMS의 Order By와 같은 기능을 제공하지 않기 때문에 결과값을 업데이트 날짜등으로 소팅해서 보여주는 것은 이 Ordered Key/Value Store가 절대적으로 유리하다.

대표적인 제품으로는 Apache의 Hbase, Cassandra 등이 있다.

3.     Document Key/Value Store

Key/Value Store의 확장된 형태로, 기본적으로는  Key/Value Store이다. Key에 해당하는Value 필드에 데이타를 저장하는 구조는 같으나, 저장되는 Value의 데이타 타입이Document 라는 타입을 사용하는데, Document 타입은 MS-WORD와 같은 문서를 이야기 하는것이 아니라, XML,JSON,YAML과 같이 구조화된 데이타 타입으로, 복잡한 계층 구조를 표현할 수 있다.



아울러, Document Store 기반의 NoSQL은 제품에 따라 다르기는 하지만 대부분 추가적인 기능 (Sorting,Join,Grouping)등의 기능을 제공한다.

대표적인 제품으로는 MongoDB,CouchDB,Riak 등이 있다.


그리고 여기서는 구체적으로 다루지 않지만 Graph나 Tree구조와 같은 데이타 구조를 저장하기 위해서 최적화된 Neo4J등의 NoSQL이 있다. 만약에 테이블 구조의 데이타가 아니라 Graph 구조의 데이타를 저장하고자 한다면 Neo4J를 한번 체크해보기 바란다.


RDBMS와 NoSQL의 차이

NoSQL이 DBMS라고 생각해서 RDBMS와 같은, 또는 떨어지지만 유사한 기능을 제공할것이라고 생각하면 큰 오산이다. NoSQL은 데이타를 저장한다. 그리고 Key에 대한 Put/Get만 지원한다. RDBMS로 치자면

Put : Insert into TABLE VALUES(KEY,value1,value2,…,valuen)

Get : Select * from TABLE where KEY=”key”

만 딱 지원한다. 물론 제품에 따라서 기능에 대한 지원 범위는 다르기는 하지만, 공통적으로 고민해야 하는 기능은

Ÿ   Sorting (SQL의 Order By)

Ÿ   Join (RDBMS에서 두개의 Table을 Foreign Key를 이용하여 join)

Ÿ   Grouping (SQL문의 group by)

Ÿ   Range Query (where key>”start” and key<”end” 와 같이 일정 범위내의 내용을 쿼리해오는 기능)

Ÿ   Index (RDBMS에 Index를 지정하여 select query 성능을 높이는 기능)

이다. RDBMS에서는 너무나도 익숙하게 사용했던 기능들이기 때문에, 막상 이 기능들을 빼고 데이타를 다루고자 하면 매우불편하다. 여기서는 이러한 기능들을 “NoSQL 데이타 모델링 패턴” 소개를 통해서NoSQL에서 어떻게 구현할 수 있는지 알아볼 것 이다.

NoSQL 데이타 모델링 시작하기

NoSQL 데이타 모델링이란, NoSQL에 저장할 데이타들의 구조, 즉 테이블 설계를 하는 것을 정의한다. NoSQL도 DBMS이기는 하지만, 우리가 지금까지 익숙하게 사용해왔던, RDBMS와는 그 특성이 매우 다르기 때문에 접근 방법을 바꿔야 한다.

NoSQL과 RDBMS의 데이타 모델링 차이

NoSQL을 사용해서 데이타 모델링을 하려면 근본적인 사상 2가지를 바꿔야 한다.

1)     개체 모델 지향에서 쿼리 결과 지향 모델링

RDBMS의 모델링 기법은, 저장하고자하는 도메인 모델을 먼저 분석한 후에, 개체간의 관계(relationship)를 식별하고, 테이블을 추출해내고, 테이블을 이용하여 쿼리를 구현하여 결과를 뽑아내는 방식이다.

NoSQL의 경우에는 이 접근 방법을 역순으로 진행해야 한다.

RDBMS가 도메인 모델 à [테이블 à 쿼리] 순서로 진행을 했다면, NoSQL은 도메인 모델 à [쿼리 결과 à 테이블] 순서로 테이블을 디자인해야 한다. RDBMS의 경우 여러가지 최적화된 기능으로 테이블을 가지고 자유롭게 쿼리 결과를 뽑아낼 수 있지만, NoSQL의 경우 복잡한 쿼리 기능이 없기 때문에, 반대로 도메인 모델에서 어떤 쿼리 결과가 필요한지를 정의한후에, 이 쿼리 결과를 얻기 위한 데이타 저장 모델을 역순으로 디자인해야 한다.

2)     정규화(Normalization)에서 비정규화(Denormalization)

RDBMS 모델링에서는 데이타의 일관성과 도메인 모델과의 일치성을 위해서 데이타 모델을 정규화한다. 그중에서도 같은 데이타가 두개 이상의 테이블에 중복되게 저장하는 것을 제거 하는데, NoSQL은 반대의 접근 방법이 필요하다. 쿼리의 효율성을 위해서 데이타를 정규화하지 않고, 의도적으로 중복된 데이타를 저장하는 등의 비정규화된 데이타 모델 설계 방식으로 접근해야 한다.

NoSQL 데이타 모델링 절차

그러면, RDBMS와 NoSQL의 두가지 결정적인 차이를 인식하고, NoSQL 기반의 데이타 모델링 절차를 살펴보자.

1.     도메인 모델 파악

먼저 저장하고자하는 도메인을 파악한다. 어떤 데이타 개체가 있는지 개체간의 관계는 어떻게 되는지등을 분석하고 ERD를 그려서 도식화 한다. RDBMS의 모델링 접근 방법이고, NoSQL에서는 이렇게 하지 않고 바로 애플리케이션 관점으로 접근하는 경우도 많은데, 도메인 모델 분석 없이 필자의 경우에는 이런 방식에는 반대이다. NoSQL도 데이타베이스이고 저장할 데이타에 대한 명확한 이해 없이는 제대로된 데이타 모델이 나올 수 없다.

다음은 간단한 블로그 시스템의 데이타 도메인 모델이다. 이 블로그 시스템은

Ÿ   사용자 ID 기반으로 블로그의 분류(Category)를 가지고 있고,

Ÿ   분류별로 글을 작성할 수 있으며,

Ÿ   글에 파일을 첨부할 수 있고,

Ÿ   댓글을 달 수 있는 블로그이다.

Ÿ   이번 예제에서는 검색이나 페이징 기능은 제외한다. (단순화 하기 위해서)



2.     쿼리 결과 디자인 (데이타 출력형태 디자인)

다음으로 가장 중요한 과정인 쿼리 결과 디자인이다. “도메인 모델”을 기반으로 애플리케이션에 의해서 쿼리 되는 결과값을 먼저 정해야 한다.

앞서 예를 든 블로깅 시스템을 다시 살펴보자



     화면 좌측 상단에는 블로그 사용자의 포스팅 분류명들을 목록 식으로 출력한다.

     포스팅 출력 화면에는 상단에, 포스팅의 분류명과 제목을 출력하고 다음에는 포스팅 날짜, 본문 내용을 출력한다.

     다음에는 첨부파일들을 출력하는데, 첨부파일 업로드 날짜와 파일명을 차례대로 출력하고, 파일에 대한 링크를 출력한다.

     마지막으로 댓글을 출력하는데, 댓글에는 작성일과, 작성자 이름과 댓글 내용을 출력하고, 작성자 이름에는 이메일을 링크한다.

이 출력 형식을 기반으로, 어떤 쿼리가 필요한지를 정의해보자

     전체 분류 출력

select categoryID,name from Category where userID=”사용자ID”

     포스팅의 분류,제목,날짜,본문 출력

select po.postID,po.Contents,po.date,ca.name 
from Category ca,Post po
where userID=”사용자ID”
order by date desc

     첨부 파일 출력

select fileID,filename,date,fileLocation
from Attachment
where userID=”사용자ID” and postID=”현재 포스팅 ID”
order by date desc

     댓글 출력
select userID,email,Contents,date
from Comment
where userID=”사용자ID” and postID=”현재 포스팅 ID”
order by date desc

대략적으로 4개의 쿼리가 필요하다. (물론 RDBMS 실제 구현에서는 좀더 최적화 할 수 있겠지만, 이해를 돕기 위해서 단순 구현하였다.) 그러면, 어떤 형태의 데이타 테이블들이 출력되는가?



위와 같이 애플리케이션의 출력형태에 따른 데이타를 정리할 수 있다. 사실 이것이 가장 중요하다. 앞에서도 설명했듯이, NoSQL의 데이타 모델링은 도메인 모델을 중심으로 하는 것이 아니라, 이 애플리케이션의 데이타 출력 내용을 기반으로 하기 때문이다.

3.     패턴을 이용한 데이타 모델링

애플리케이션 데이타 출력 내용을 디자인 했으면, 이제 이 내용을 가지고 NoSQL에 정의될 데이타 모델링을 들어간다. NoSQL은 Sorting,Grouping,Join 등의 RDBMS 기능을 제공하지 않기 때문에 이를 배제하고 Put/Get으로만 데이타를 가지고 올 수 있는 형태로 데이타 모델 즉 NoSQL내의 테이블을 재 정의 해야 한다.

이 데이타 모델링을 돕기위해서 다음 챕터에서는 NoSQL 데이타 모델링 기법을 다시 설명한다. 이 때 가장 중요한것은 Demoralization이다. 데이타를 가급적 중복으로 저장하여, 한번에 데이타를 읽어오는 횟수를 줄이도록 한다. (이 IO자체가 엄청난 부담이기 때문에)

위의 블로깅 시스템 데이타를 일반적인 NoSQL 스타일로 바꾸면 다음과 같다.



특히 Key 부분을 주목해 볼 필요가 있는데, Join을 없애기 위해서, 아예 userID나 postID를“:”로 구분되는 deliminator로 하여 Key에 포함시켜 버렸다. 이는 Join을 없애는 것 이외에 다른 이유가 또 있는데, Ordered Key/Value Store의 경우에는 Key를 기반으로 소팅을 하기 때문에 첫번째, 포스트 ID를 Sequential하게 증가 시켜 나가면, 같은 사용자의 글의 경우에는Sorting 이 가능하다. 두번째, Grouping인데, 포스팅을 출력하는 사용자에 대해서 posting을 쭈욱 출력해 나가면, 순차적으로 Post가 출력이 되다가, 해당 사용자의 포스팅 데이타가 끝이나면, Key의 맨앞 userID가 다른 사용자id로 바뀌기 때문에 where문장이 없이도, 특정 사용자의 포스팅을 순차적으로 출력할 수 있다. 뒤에서 설명한 데이타 모델링 패턴에서Enumerable Key와 Composite Key Index 패턴을 참고하기 바란다.


4.     최적화를 위한 필요한 기능들을 리스팅

자아 이제 약간은 NoSQL스럽게 디자인이 되었다. 이제는 NoSQL의 특성을 반영하여, 조금 더 디테일한 디자인을 할 수 있다. 다시 애플리케이션 및 데이타의 특성을 다시 한번 들여다 보자

첨부 파일 (Attachment) 파일의 경우에는 포스팅이 작성되었을 때 레코드가 추가되며, 변경이 거의 없다. 그리고 첨부파일의 수는 그리 많지 않기 때문에, 하나의 필드에 모두 몰아서 저장할 수 있다. 이렇게 하나의 필드에 여러개의 데이타를 저장할 경우에는 Document Store를 고려해 볼 수 있다.

그리고 앞에서도 언급했지만 블로그 포스트,첨부파일,댓글은 소팅이 되어야 하기 때문에, Ordered Key 형태가 필요하다.

현재 데이타 모델은 포스팅이 포스트된 순서대로만 출력하는 형태인데, 분류 개념이 있기 때문에, 분류에 따라서 포스팅을 출력하려면 분류 필드가 별도 필드로 들어가야 하고, 이 필드에 따라 where문으로 select할 수 있는 기능이 있어야 한다. 마치 RDBMS의 Index같은 개념이 필요한데, 이러한 기능을 NoSQL에서는 Secondary Index라고 한다.



이런 옵션등을 적용해보면 Posting 테이블은 위와 같이 변경해볼 수 있다.

여기서 고려해야 할점 하나를 짚고 넘어가자..!!

NoSQL 제품들은 KV, Ordered KV, Document Store등 데이타 모델로는 3가지 분류로 분리가 되긴 하지만, 세세한 내부 아키텍쳐나 기능들은 매우 다르다.  아주 자세하게는 아니더라도, 어떤 NoSQL 제품군이 있고, 대략적인 기능이 어떻게 되는지를 알아야, 이 정도 수준의 설계를 할 수 있다. 물론 이 단계까지 설계되더라도 아직까지 완벽하지 않다.

솔루션들이 스펙상에 “OOO 기능이 있다.” 하더라도, 그 기능이 제대로 돌아가는 건 아니다. Secondary Index의 경우 Cassandra나 Riak에서 지원은 하지만 실제 부하를 줘 가면서 테스트를 해보면 성능이 잘 안나오는 경우가 많고, 내부 구조상으로도 고성능을 내기가 어려운 구조이다. 그래서 이런 부가 기능들은 직접 내부 구조를 분석하고, 테스트를 해봐야 사용 가능 여부를 판단할 수 있다.

예전의 RDBMS야, 워낙 레퍼런스도 많고, 벤더 지원도 있기 때문에, 써야할, 쓰지 말아야할 기능이 명확하지만 NoSQL의 경우는 제품도 많을 뿐더라, 기술도 신기술이기 때문에 서적조차 드물다. 직접 분석하고 테스트해보는 방법 밖에 없다.


5.     후보 NoSQL을 선정 및 테스트

앞에서 언급한 바와 같이, 모델링한 데이타 구조를 효과적으로 실행할 수 있는 NoSQL을 찾아야 한다. 이는, NoSQL에 대한 구조 및 특성 분석 후에, 실제로 부하 테스트, 안정성, 확장성 테스트를 거친 후에, 가장 적절한 솔루션을 선택해야 한다.

경우에 따라서는 하나의 NoSQL이 아니라, 여러개의 NoSQL을 복합해서 사용할 경우도 있다.트위터나,페이스북같은 대규모 서비스들은 하나의 NoSQL만을 사용하지 않고 데이타의 성격과 업무의 목적에 맞는 다수의 NoSQL을 선정하여 사용한다.


6.     데이타 모델을 선정된 NoSQL에 최적화 및 하드웨어 디자인

마지막으로 선정된 NoSQL을 기반으로 다시 데이타 모델을 최적화 하고, 이에 맞는 애플리케이션 인터페이스 설계와 하드웨어에 대한 디자인을 진행해야 한다.


지금까지 간단하게나마 NoSQL의 데이타 모델링 절차에 대해서 알아보았다. 다시 한번 강조하지만NoSQL의 데이타 모델링 방식은 RDBMS가 데이타 자체의 관계를 중요시 하고, 데이타에서부터 출발한다면, NoSQL은 애플리케이션이 출력하고자 하는 데이타 출력 내용에 따라서 데이터 모델링이 완성된다. RDBMS와 역순으로 진행되어야 하고, 데이타 중심이 아니라, 애플리케이션 중심으로 모델링을 진행해야 한다.

그리고 NoSQL은 신 기술 분야이면서 오픈 소스 진영이 주를 이르고 있기 때문에, 기술 지원을 받기가 매우 어렵다. 물론 외국에는 NoSQL에 대해서 유상으로 기술 지원을 해주는 업체들이 있기는 한데, (Cassandra의 경우 DataStax가 기술 지원을 하고, Riak은 Basho, MongoDB는 10gen 등이 기술 지원을 한다.). 국내 실정상 외국엔지니어를 불러다가 기술 지원을 받기도 힘들뿐더러, 기술 지원 회사의 규모가 작기 때문에 숙력된 엔지니어를 필요할때 마다 부르기도 어렵다.

그리고, Amazon등에서 검색해보면 알겠지만, NoSQL에 대한 서적도 그리 많지 않은 편이기 때문에 공부하기도 어렵다. 해외에서 이러한 NoSQL류를 쓰는 업체들은 스스로 내부 개발자들을 역량을 키워서 공부하고, 테스트해서 내재화된 기술을 기반으로 NoSQL을 운용하기 때문에, 단순하게 솔루션 도입 관점에서만 볼 것이 아니라, 기술 내재화 관점에서도 NoSQL 도입을 고려해야 한다.


다음글에서는 NoSQL의 데이타 모델링을 하기 위한 일반적은 데이타 모델링 패턴에 대해서 소개하기로 한다.


출처 - http://bcho.tistory.com/665






NoSQL 데이타 모델링 #2

Facebook Server Side Architecture Group
http://www.facebook.com/groups/serverside
조대협

NoSQL 데이타 모델링 패턴

NoSQL 데이타 모델링 패턴[1]은 Key/Value 저장 구조에 Put/Get 밖에 없는 단순한 DBMS에 대해서 다양한 형태의 Query를 지원하기 위한 테이블을 디자인하기 위한 가이드 이다.

특히 RDBMS에는 있는

“ Order by를 이용한 Sorting, group by를 이용한 Grouping, Join등을 이용한 개체간의 relationship정의, 그리고 Index 기능”

들을 데이타를 쿼리하는데, 상당히 유용한 기능인데, NoSQL은 이러한 기능들을 가지고 있지 않기 때문에, NoSQL 내에서 데이타 모델링을 통해서 이러한 기능들을 구현하는 방법에 대한 가이드를 제공한다.


1. 기본적인 데이타 모델링 패턴

NoSQL의 데이타 모델링을 할때, 가장 기본적으로 많이 사용되는 패턴들이다.


1)    Denormalization

Denormalization은 같은 데이타를 중복해서 저장하는 방식이다.
Denormalization을 하면, 테이블간의 JOIN을 없앨 수 있다. NoSQL에서는 JOIN을 지원하지 않기 때문에, 두 테이블을 조인해서 데이타를 가지고 오는 로직을 구현하려면, 각 테이블에서 데이타를 각각 가져와서 애플리케이션에서 합쳐야 하기 때문에, 2번의 IO가 발생한다.

Denormalization을 적용하여, 하나의 테이블에 JOIN될 데이타를 중복 저장하게 되면 1번의 IO로도 데이타를 가지고 올 수 있다.

예를 들어서 사용자 정보를 저장하는 User 테이블과, 도시 이름을 저장하는 City 테이블이 있다고 하자,



이런 테이블 구조에서 “사용자별로 이름,나이,성별,우편번호” 를 출력하는 쿼리는 다음과 같다.

select u.name,u.age,u.sex,c.zipcode from user u,city c where u.city = c.city

이 테이블 구조를 그대로 해서, NoSQL에서 구현하면

select $city,name,age,sex from user where userid=”사용자ID”

select zipcode from city where city=$city

식으로 구현해야 하는데, User 테이블에서 city값을 읽어온 후에, City 테이블에서 앞서 읽어온그래city값을 키로 해서 다시 zip code를 찾아와야 한다. 두번 쿼리를 발생 시킨다. 단순한 예이지만, Join을 해야 하는 테이블 수가 많을때는 NoSQL로의 IO수가 훨씬 더 늘어난다. 이 IO 수를 줄이려면,아예 처음부터 Join이 되어 있는 테이블을 하나 더 만들어 버리면 된다.



이런식으로 새로운 테이블을 추가하면 된다.

Denormalization을 이용하여 중복을 허용하였을 경우에 장단점은 다음과 같다.

장점은

Ÿ   성능 향상 – Join을 위해서 몇번씩 쿼리를 하지 않아도 되기 때문에, 당연히 쿼리 성능이 올라간다.

Ÿ   쿼리 로직의 복잡도가 낮아짐 – Join에 대한 로직이 필요 없이, 한번에 데이타를 가지고 오기 때문에, 쿼리 로직이 단순해 진다.

   반대로 다음과 같은 단점을 불러온다.

Ÿ   데이타 일관성 문제 발생 가능 – age,sex,zip code등을 insert하거나 update하였을때, User, City 테이블뿐만 아니라 UserZipCode 테이블도 업데이트 해줘야 한다. 만약에 같은 User 테이블을 업데이트 하다가 에러가 났을 경우, UserZipCode 테이블은 업데이트가 안된 상태이면, 양쪽 테이블에 데이타 불 일치성이 발생할 수 있다.

Ÿ   스토리지 용량 증가 : 데이타를 중복해서 저장하는 만큼 스토리지 용량이 증가 된다.

사실 보면 단점도 있지만, NoSQL의 경우 Join이 어렵고, 애플리케이션 적으로 구현을 한다고 해도 성능이 안나오거나 구현이 어려운 경우가 많기 때문에, Denormalization을 통한 중복은 상당히 효과적인 모델링 패턴이 된다.


2)    Aggregation

드롭박스나, 슈가싱크처럼 파일을 저장하는 개인 스토리지 서비스가 있다고 가정하자. 이 서비스는 파일에 대한 정보를 저장하고, 음악,동영상,사진 등의 파일의 종류에 따라서 추가적인 메타 정보를 저장한다. ERD를 기준으로 개체를 표현해보면 다음과 같다.



NoSQL의 재미있는 특성중의 하나가 Scheme-less 또는 Soft Scheme라는 특성인데, RDBMS의 경우 테이블에 데이타를 넣을때, 반드시 테이블의 구조에 맞도록 넣어야 한다. 컬럼수와 이름도 지켜야 하고, 각 컬럼에 해당 하는 데이타 타입도 준수해야 한다 또한 모든 ROW는 같은 컬럼을 가져야 한다.  반면 NoSQL의 경우에는 Key만 똑같다면, 각 Row는 제멋대로라도 상관없다. 꼭 같은 컬럼을 가질 필요도 없고, 데이타 타입도 각기 틀려야 한다. Value에 저장되는 Row 데이타들은 한줄의Row 구조를 가지기는 하지만, 전체 테이블에 대해서 그 Row 구조가 일치할 필요가 없다. 이를 데이타가 구조는 가지고 있지만, 구조가 각각 틀리는 것을 허용한다고 해서 Soft-Scheme 또는Schemeless 라고 한다.

이 특성을 이용하면, 위의 데이타 모델을 하나의 테이블로 합칠 수 있다



1:N과 같은 복잡한 엔터티들의 관계를 손쉽게 하나의 테이블로 바꿀 수 있고, 이는 결과적으로Join의 수를 줄여서 Query 성능을 높이는 방법이 된다.


3)    Application Side Join

NoSQL은 Join이 거의 불가능하다. (지원하는 제품도 있지만). 그래서 Denormalization이나Aggregation 그리고 앞으로 설명할 데이타 모델링 패턴을 사용하는 것인데, 그래도 어쩔 수 없이Join을 수행해야할 경우가 있다. 이 때는 NoSQL의 쿼리로는 불가능하고, NoSQL을 사용하는 클라이언트 Application단에서 로직으로 처리해줘야 한다.

예를 들어서 TABLE 1,2 두개의 테이블이 있고, TABLE 1의 컬럼중 하나가 Foreign Key로써TABLE 2의 데이타를 가르키고 있다면, Application Join을 하려면, Table 1에서 Primary Key로 한 Row를 읽어온 후에, Table 2를 가르키는 컬럼의 값을 Key로 해서, 다시 Table 2에서 쿼리를 해온다.



Application Side Join은 Join이 필요한 테이블 수 만큼 NoSQL로의 Request/Response IO가 발생하는 만큼 다소 부담 스럽기는 하지만, 반대로 Denormalization등에 비해서는 스토리지 사용량을 절약할 수 있다.


참고 : Map & reduce 기능을 이용한 Server Side Join

Application Side Join이 있다면, 반대로 Server Side Join 기능도 있다. NoSQL에는 Join 기능이 없다고 했는데, Server Side Join은 무엇인가?


Riak이나 MongoDB와 같은 일부 NoSQL DB들은 RDBMS의 stored procedure [2]를 지원한다. Map & Reduce [3]라는 이름으로 이 기능을 지원한다. 즉 위에서 Application에서 수행한 로직을NoSQL 서버들 내에서 수행해서 리턴하는 방식이다. 이 로직들은 NoSQL에서 지원하는 언어를 통해서 구현된후, NoSQL 엔진위에서 수행된다.




이렇게 하면, Application에서 NoSQL로의 호출이 Map & Reduce function 한번만 호출하면 되기 때문에, 네트워크 IO를 줄여서 성능을 향상 시킬 수 있다. 반면, Join에 대한 로직이 NoSQL 서버 쪽에서 수행되기 때문에, 반대로 NoSQL에 대한 부담이 가중된다.


2. 확장된 데이타 모델링 패턴

1)    Atomic aggregation

NoSQL에서 고민해야할 것 중의 하나의 두 개이상의 테이블을 업데이트 할때, 트렌젝션에 관리에 대한 문제이다. 그림과 같이 두개의 테이블을 업데이트 하는 시나리오에서, 1번 테이블을 업데이트 한 후에, 애플리케이션 로직이나 NoSQL의 장애로 인해서 2번 테이블이 업데이트가 되지 않는 문제가 발생할 수 있다.



이 경우 데이타의 일관성 문제를 야기하는데, 이에 대한 해결 방안으로 생각할 수 있는 것은, TABLE 1,2를 하나의 테이블로 합쳐 버리는 것이다.



하나의 테이블에 대해서는 NoSQL도 atomic operation(원자성)을 보장하기 때문에, 트렌젝션을 보장 받을 수 있다. 구현 패턴상으로는 Aggregation과 동일한데, Aggregation은 1:N의relationship을 aggregate해서 join을 없애기 위함이고, Atomic Aggregation은 트렌젝션 보장을 통한 데이타 불일치성을 해결하기 위함이다.

예를 들어 사용자 정보가 UserAddress,UserProfile,UserId라는 이름의 3개의 테이블로 분산이 되어 있을때, 사용자를 생성하는 경우, 이 3개의 테이블에 Insert를 해줘야 한다. 그러나 테이블이 3개로 분산되어 있기 때문에, 앞에서 언급한 장애시 트렌젝션에 대한 보장이 되지 않는다. 이를 해결하기 위해서 atomic aggregation 패턴을 적용하여, 이 3개의 테이블을 User 테이블의 필드로 집어 넣게 되면, 하나의 테이블이기 때문에, 장애나 에러로 인한 트렌젝션 불일치 문제를 방지할 수 있다.



2)    Index Table

NoSQL을 RDBMS 처럼 Index가 없기 때문에, Key 이외의 필드를 이용하여 Search를 하면, 전체Table을 Full Scan 하거나 아니면 Key이외의 필드에 대해서는 아예 Search가 불가능하다. 이 문제를 해결하기 위해서 Index를 위한 별도의 Index Table을 만들어서 사용할 수 있는데, 상당히 사용 빈도가 많은 방법이다.

예를 들어, 파일 시스템을 NoSQL에 저장한다고 했을때, 파일 테이블은 다음과 같은 구조를 갔는다.



여기서 특정 디렉토리에 있는 파일만을 리스트업 하고 싶다면, 별도의 Index Table을 다음과 같이 만들면 된다.



Cassandra나 Riak과 같은 일부 NoSQL에는 제품적으로 secondary Index라는 이름으로 Key 이외의 필드를 Index로 지정하는 기능을 가지고 있는데, 이 기능들은 아직까지 성숙되지 못해서, 여기서 설명하는 Index Table을 사용하는 것보다 성능이 나오지 않는다. 만약에 NoSQL에 있는Secondary Index 기능을 사용할 예정이라면, 반드시 이 Index Table 패턴과 성능을 비교해보기를 추천한다. 당연히 Secondary Index를 이용하면 구현은 조금 편리해질 수 있지만, 성능 차이가 많이 날 수 있다.


3)    Composite Key

이 글을 읽으면서 눈치가 빠른 사람이라면, Key를 정의하는데, “:” deliminator를 이용하여 복합키를 사용하는 것을 눈치 챘을 것이다. NoSQL에서는 이 Key를 어떻게 정의하느냐가 매우 중요하다.특히 Ordered KV Store 의 경우에는 이를 이용하여 order by와 같은 sorting 기능이나grouping을 구현할 수 있다. Composite Key는 하나 이상의 필드를 deliminator를 이용하여 구분지어 사용하는 방법으로 RDBMS의 복합키 (Composite primary key)와 같은 개념이라고 생각하면 된다. 단지 RDBMS의 경우에는 여러개의 컬럼을 묶어서 PK로 지정하지만 NoSQL은 한컬럼에deliminator를 이용하여 여러개의 키를 묶어서 넣는다.

아래의 예제를 보자, PC의 디렉토리를 Ordered KV Store에 저장한다고 하자.
 windows 하위 디렉토리를 가지고 올때, “windows:etc” 부터 쿼리를 해서, 다음 row를 반복적으로 쿼리해서, key가 windows로 시작하지 않을때 까지 읽어오면, windows 디렉토리의 하위 디렉토리를 모두 가지고 올 수 있다.



노드가 추가,삭제되더라도, 내부적으로 sorting이 되기 때문에, 문제없이 사용이 가능하다.

단, Key값을 선택할때 주의해야할 사항은 “특정 서버로의 몰림 현상” 을 들 수 있다. NoSQL은 특성상, N개의 서버로 구성된 클러스터이다. 그리고 데이타는 Key를 기준으로 N개의 서버에 나눠서 저장이 된다. 예를 들어 Key Range가 A~Z 26개라고 가정하고, 클러스터의 서버 수가 26대라고 하면, 각 서버는 Key의 시작으로 사용되는 알파벳 키들의 데이타를 저장한다. 1번은 A로 시작되는Key 데이타들, 2번은 B로, 3번은 C로 등등.

이 Key 값을 “City:User Name”으로 했다고 가정하자, 우리나라에서는 5000만 인구중, 1/5인1000만이 서울에 살고 있다. 그래서 데이타중 약 20%의 키는 “Seoul:xxx”로 시작할 것이고 26대의 서버중에서 S로 시작하는 키를 저장하는 한대의 서버는 20%의 부하를 처리하게 될것이다. 서버가 26대이니까는 각 서버는 1/26 (약 3.8%)의 부하를 처리해야 하는데, 이건 예상치 보다 5배 이상 많은 로드를 처리하기 때문에 성능 저하를 유발할 수 있다. 이런 이유로, Key를 선정할 때는 전체 서버에 걸쳐서 부하가 골고루 분산될 수 있는 Key를 선정하는 것이 좋다.


4)    Inverted Search Index

검색엔진에서 많이 사용하는 방법인데, 검색엔진은 사이트의 모든 페이지를 검색 로봇이 검색해서 문서내의 단어들을 색인하여 URL에 맵핑해서 저장해놓는다.



검색은 단어를 키로 검색이 되기 때문에, 위의 테이블 구조에서는 value에 검색 키워드들이 들어가 있기 때문에, 효과적인 검색을 할 수 없다. 이 검색 키워드를 키로 해서 URL을 value로 하는 테이블을 다시 만들어 보면, 아래와 같은 식으로 표현되고, 검색 키워드로 검색을 하면 빠르게, 검색 키워드를 가지고 있는 URL을 찾아낼 수 있다.



이렇게 value의 내용을 key로 하고, key의 내용을 반대로 value로 하는 패턴을 inverted search index라고 한다.


5)    Enumerable Keys

NoSQL 솔루션에 따라서, RDBMS의 Sequence와 같은 기능을 제공하는 것들이 있다. 이 기능들은, 키에 대해서 자동으로 카운터를 올려주는 기능을 가지고 있다. (예를 들어 첫번째 키는 1, 두번째 키는 2,다음은 3,4,5 식으로 순차적으로 연속된 키를 부여해주는 기능).

이 기능은 데이타에 대한 traverse 기능을 제공한다. 즉, 100번 키를 가지고 왔는데, 이 앞뒤의 값을 알 수 있다. Sequential한 키를 사용했기 때문에, 당연히 앞의 키값은 99, 다음 키값은 101로 해서 값을 가지고 올 수 있다.


3. 계층 데이타 구조에 대한 모델링 패턴

NoSQL들은 데이타 모델이 KV,Ordered KV,Document들 여러가지가 있기는 하지만, 기본적으로row,column을 가지고 있는 테이블 구조 저장구조를 갖는다. 애플리케이션 개발중에는 이런 테이블 구조뿐만 아니라 Tree와 같은 계층형 데이타 구조를 저장해야 할 경우가 있는데, 테이블 구조의 저장 구조를 갖는 NoSQL의 경우 이러한 계층형 구조를 저장하는 것이 쉬운일은 아니다.

RDBMS의 경우에도 이런 계층형구조를 저장하기 위해서 많은 고민을 했는데, RDBMS 솔루션에서 기능적으로 자체 지원할 수 도 있고, 데이타 모델링을 통해서도 이러한 계층형 구조를 저장할 수 있다.

여기서 소개하는 NoSQL에서 계층형 구조를 저장하는 기법은 RDBMS에서 사용하는 기법들을 많이 참고하였다. 추가적인 기법은 RDBMS의 Tree구조 저장 기법을 참고하기 바란다.


1)    Tree Aggregation

Tree 구조 자체를 하나의 Value에 저장하는 방식이다. JSON이나 XML 등을 이용하여, 트리 구조를 정의 하고, Value에 저장하는 방식이다.

Tree 자체가 크지 않고, 변경이 많이 없는 경우에는 사용하기 좋다. “계층형 게시판의 답글 Tree 구조” 등을 저장하기에 용이하다.


2)    Adjacent Lists

Adjacent List 구조는, 전통적인 자료 구조에서 사용하는 Linked List와 같은 자료 구조형을 사용하여, 각 Tree의 노드에 parent node에 대한 포인터와 child node들에 대한 포인터를 저장하는 방식이다.

Tree의 내용을 검색하려면, root 노드에서 부터 child node를 child node 포인트를 이용하여, 값을 가져오는 방식이다. (이를 Tree traversing 이라고 한다.)

특정 노드만 알면, 해당 노드의 상위, 하위 노드를 자유롭게 traversing할 수 있어서 traversing에는 장점을 가지고 있지만, 반대로, 하나의 노드를 이동할 때마다, 포인터를 이용해서 매번 쿼리를 해와야 하기 때문에, Tree의 크기가 크다면 NoSQL로의 IO가 엄청나게 많이 발생한다. (트리의 노드 수가 N이면, N번 쿼리를 해야 한다)

아래 그림을 보자, 파일 디렉토리를 저장하는 자료 구조를 만든다고 했을때, Directory라는 테이블을 정의하고, 이 테이블에는 directory 명과, 해당 directory의 상하위 디렉토리 이름을 저장하도록 한다.

이를 바탕으로 테이블에 저장된 데이타를 보면 아래와 같다.



구현이 쉬운 편이긴 하지만 Tree 구조 traverse에 많은 IO를 유발하기 때문에, 큰 Tree구조를 저장하거나 잦은 read가 있을때는 권장하지 않는다.

     RDBMS 의 경우에는 이런 Tree 구조 traversing을 지원하기 위해서 recursive 쿼리에 대해서native recursive function을 지원함으로써, tree 구조 저장을 지원하는 경우도 있다.


3)    Materialized Path

Materialized Path는 Tree 구조를 테이블에 저장할때, root에서 부터 현재 노드까지의 전체 경로를 key로 저장하는 방법이다.

이 방법은 구현에 드는 노력에 비해서 매우 효율적인 저장 방식이다. 특히 Key에 대한 Search를 할때, Regular Expression을 사용할 수 있으면, 특정 노드의 하위 트리등을 쿼리해 오는 기능등 다양한 쿼리가 가능하다. 일반적은 KV나 Ordered KV에서는 적용하기는 힘들지만, MongoDB와 같은Document DB는 Regular Expression을 지원하기 때문에, 효과적으로 사용할 수 있다.



4)    Nested Sets

Netsted Set의 기본원리는 Node가 포함하는 모든 Child Node에 대한 범위 정보를 가지고 있다.먼저 예를 보고 설명하자. 각 Node는 배열이나 리스트에 Sorting된 형태로 저장되어 있다.

각 Node는 자신이 포함하는 모든 Sub Tree (Child Node)들이 포함된 start와 end index를 저장한다.

아래 A는 전체 Sub Tree를 포함하기 때문에 2~9번에는 A Sub Tree의 내용이 된다.
C 노드의 경우 자신이 포함하는 모든 Child Node는 4~9에 포함되어 있기 때문에, Index를 4~9로 저장한다.



각 노드만 안다면, Sub Tree를 start,end index만 있으면 쭈욱 읽어오면 되기 때문에 매우 빠른 성능을 보장할 수 있다. 단 이 데이타 구조 역시 update에 취약하다. update가 발생하였을 경우, Index를 다시 재배열해야 하기 때문에 이에 대한 로드가 매우 크다.

위의 예제에서 B 노드 아래에 J 노드를 추가해보자, J 노드의 index는 3이 되어야 하고, 3번 Index부터는 모두 +1 씩 더해져야 하며, Child Node의 값 역시 모두 변화 되어야 한다.



트리 생성 후에, 변화가 없는 대규모 트리등을 저장하는데 유용하게 사용할 수 있다

.

결론

지금까지 몇가지 NoSQL 적용시 사용할 수 있는 데이타 모델링 패턴에 대해서 살펴보았다. 기본 패턴은 대부분의 NoSQL 솔루션에 적용할 수 있으며, 확장된 모델링 패턴의 경우에는 NoSQL이 지원하는 기능이나 데이타 구조 (KV, Ordered KV,Document etc)에 따라서 적용할 수 있다.

NoSQL을 이용한 시스템을 개발할때는

1.     데이타 모델링이 80% 이상이다. 선정한 NoSQL과 애플리케이션의 특성에 맞는 데이타 모델링에 집중하자.

2.     NoSQL은 어떤 솔루션이 좋다, 나쁘다가 없다. 어떤 솔루션이 특성이 어떻다는 것만 있기 때문에 반드시 데이타 모델과 내부 아키텍쳐 두 가지를 파악한 후에, 애플리케이션의 특성에 맞는NoSQL을 선정해야 한다.

3.     하나의 NoSQL로 전체 데이타를 저장하려고 하지 마라. NoSQL은 데이타 구조가 매우 다눈하지만, 애플리케이션들은 하나의 단순한 데이타 구조로 저장할 수 없는 데이타가 반드시 존재한다. RDBMS와 혼용하거나, 다른 NoSQL과 혼용하거나 성능면에서는 캐슁 솔루션과 혼용하는 것을 반드시 고려 해야한다.

NoSQL은 놀라온 성능과 확장성을 제공하지만, 많은 연구와 노력이 필요하다. Oracle과 같은 데이타베이스를 사용할때도, 전문 DBA를 두고, 튜닝에 시간을 두고, 데이타 모델을 가꾸고, 튜닝을 하지 않는가? NoSQL이 오픈소스를 중심으로 사용되고 있지만, 오픈 소스라서 쉬운게 아니다. 그만큼 많은 투자와 연구와 노력이 필요한 만큼, 신중하게 검토하고 도입을 결정하기를 바란다.


[2] RDBMS에서 프로그래밍 언어를 이용해서 구현된 사용자 정의 데이타 Query 함수. 예를Oracle 들어RDBMS의 경우에는 PL/SQL이라는 프로그래밍 언어를 이용하여, 데이타 베이스에 대한 비지니스 로직을 구현해서 저장해놓고, 클라이언트에서 이 함수를 호출해서 사용하게 할 수 있다.

[3] Map & Reduce는 Input 데이타를 여러 조각으로 쪼갠 후, 여러대의 서버에서 각 데이타 조각을 처리한후(Map), 그 결과를 모아서 (Reduce) 하나의 결과를 내는 분산 처리 아키텍쳐 이다.




링크 

NoSQL 데이타 모델 및 데이타 모델링 절차 : http://bcho.tistory.com/665

참고 자료 http://www.pearltrees.com/#/N-u=1_752336&N-p=53126547&N-play=1&N-fa=5793524&N-s=1_5827086&N-f=1_5827086






'DB > NoSQL' 카테고리의 다른 글

nosql - 개념 설명  (0) 2013.04.29
nosql - reference site  (0) 2013.04.29
nosql - 주의 사항  (0) 2013.04.29
nosql - list  (0) 2013.04.29
NoSQL - 소개  (0) 2013.04.29
Posted by linuxism
,

NoSQL - 소개

DB/NoSQL 2013. 4. 29. 02:14


근래에 들어서 기술의 빅 트렌드 중의 하나는 빅데이터와 NoSQL이다. 빅데이터와 NoSQL은 대용량의 데이터를 빠른 시간에 안전하게 처리할 수 있는 기술이기에 각광을 받고 있지만, 기술적 난이도도 높고 기능적 제약도 많은 탓에 일반적인 기업에서 제대로 된 이해 없이 도입했다가 오히려 낭패를 보는 경우가 많다. 이 글에서는 NoSQL의 등장 배경과 정의, 그리고 특성 등을 소개함으로써 NoSQL을 정확히 이해하고, 나아가 올바른 사용법을 점검하는 기회를 마련했다.


조대협 bwcho75@gmail.com|자바스터디 초대 운영자, 한국자바개발자협의회(JCO)의 1대 부회장을 거쳤고 현재 개인 블로그(http://bcho.tisoty.com)와 페이스북 서버사이드 아키텍트 그룹(http://www.facebook.com/groups/ serverside)을 운영하고 있다. BEA, NHN, 오라클 등에서 웹로직 등 미들웨어 기반 미션 크리티컬 시스템과 대규모 글로벌 분산 시스템 기술 지원, 개발 컨설팅 등을 수행했으며 마이크로소프트에서 클라우드 아키텍트로 활동했다. 현재는 국내 기업에서 아키텍트로 근무 중이며 글로벌 서비스를 커버하는 대규모 분산 시스템에 대한 설계 구현 업무를 맡고 있다.

인터넷 대중화에 이어 수년 전부터 SNS 서비스가 활성화되면서 컴퓨팅 시스템에도 변화가 찾아오기 시작했다.

NoSQL의 등장 배경
예전에 컴퓨팅 시스템은 기업 업무를 자동화하고 효율화하는 데 그 목적이 있었다. 그래서 기업의 복잡한 데이터를 저장하고 그 데이터 간의 관계를 정의하고 분석하는 데 최적화되어 있었다. 기업의 업무 시스템은 해당 기업의 생산과 판매를 지원하기 위한 것이었고 거기에서 생성되는 데이터양은 한계를 가지고 있었다.

그러나 2000년대에 들어서면서 인터넷의 발전과 함께 SNS 서비스가 활성화되면서 SNS 서비스 시스템은 특정 고객이 아닌 전 세계 사람들을 대상으로 하는 형태의 서비스로 발전되었고 이는 기존의 기업 시스템에서 볼 수 없었던 대규모 데이터를 생산해냈다. 또한 이 데이터들은 기존 기업 데이터에 비해 매우 단순한 형태를 띠게 되었다.

즉 데이터의 패러다임이 한정된 규모의 복잡성이 높은 데이터에서 단순한 대량의 데이터로 넘어가기 시작했다. 이는 기존의 데이터 저장 시스템으로는 커버할 수 없는 여러 가지 한계를 야기했고 결국에는 새로운 형태의 데이터 저장 기술을 요구하게 되었다.

이때 대표적인 인터넷 기업이면서 이러한 대용량 단순 데이터를 가장 많이 보유해 단순한 대용량 데이터 처리에 대한 요구가 가장 많은 구글과 아마존에 의해 빅테이블(Bigtable)과 Dynamo라는 논문이 발표되었고, 이 두 논문은 새로운 데이터 저장 기술을 만들어내는 시발점이 되었다.

이것은 기존의 오라클 등으로 대변되는 RDBMS 중심의 데이터 저장 기술 시장에 새로운 데이터 저장 기술인 NoSQL이 등장하는 계기였다. NoSQL은 Not Only SQL의 약자로 기존 RDBMS 형태의 관계형 데이터베이스가 아닌 다른 형태의 데이터 저장 기술을 의미한다. NoSQL이라고 해서 RDBMS 제품군(MS-SQL, Oracle, Sybase, MySQL) 등과 같이 공통된 형태의 데이터 저장 방식(테이블)과 접근 방식(SQL)을 갖는 제품군이 아니라 RDBMS와 다른 형태의 데이터 저장 구조를 총칭하며, 제품에 따라 각기 그 특성이 매우 달라서 NoSQL을 하나의 제품군으로 정의할 수는 없다.

NoSQL의 특징
그럼에도 불구하고 NoSQL은 기존 RDBMS에 비해 몇 가지 공통된 특징을 가지고 있다. 이를 정리하면 다음과 같다. 

● NoSQL은 RDBMS와는 달리 데이터 간의 관계를 정의하지 않는다
가장 큰 특징 중의 하나는 관계형 데이터베이스인 RDBMS가 데이터의 관계를 Foreign Key 등으로 정의하고 이를 이용해 Join 등의 관계형 연산을 한다고 하면, NoSQL은 데이터 간의 관계를 정의하지 않는다. 데이터 테이블은 그냥 하나의 테이블이며 각 테이블 간의 관계를 정의하지도 않고 일반적으로 테이블 간의 Join도 불가능하다.

● RDBMS에 비해 훨씬 더 대용량의 데이터를 저장할 수 있다
RDBMS의 복잡도와 용량 한계를 극복하기 위한 목적으로 등장한 만큼, 페타바이트급의 대용량 데이터를 저장할 수 있다.

● 분산형 구조
NoSQL은 기존의 RDBMS와는 다르게 하나의 고성능 머신에 데이터를 저장하는 것이 아니라, 일반적인 서버(인텔 계열의 CPU를 사용하는 Commodity Server) 수십 대를 연결해 데이터를 저장 및 처리하는 구조를 갖는다. 즉 분산형 구조를 통해 데이터를 여러 대의 서버에 분산해 저장하고, 분산 시에 데이터를 상호 복제해 특정 서버에 장애가 발생했을 때에도 데이터 유실이나 서비스 중지가 없는 형태의 구조다.

● 고정되지 않은 테이블 스키마 


<표 1> RDBMS에서 간단한 테이블 구조 예제

RDBMS와는 다르게 테이블의 스키마가 유동적이다. 예를 들어 RDBMS의 경우 테이블이 <표 1>과 같은 형태로 되어 있을 때 해당 테이블은 반드시 숫자, 이름 문자열, 주소 문자열만 들어갈 수 있다.
그런데 NoSQL은 대부분 이런 개념이 없다. ID로 사용하는 키 부분에만 타입이 동일하고, mandatory(생략되지 않는) 필드로 지정하면 값에 해당하는 컬럼은 어떤 타입이든, 어떤 이름이 오든 허용된다. 즉 <표 2>와 같이 ID 필드는 공통이지만, 데이터를 저장하는 컬럼은 각기 다른 이름과 다른 데이터 타입을 갖는 것이 허용된다.


<표 2> NoSQL에서 테이블 설계 예제

CAP 이론


<그림 1> CAP 기반의 DB 분류

NoSQL은 분산형 구조를 띠고 있기 때문에 분산 시스템의 특징을 그대로 반영하는데, 그 특성 중의 하나가 CAP 이론이다. 이 이론은 2002년 버클리대학의 Eric Brewer 교수에 의해 발표된 분산 컴퓨팅 이론으로, 분산 컴퓨팅 환경은 Consistency, Availability, Partitioning 세 가지 특징을 가지고 있으며, 이중 두 가지만 만족할 수 있다는 이론이다. NoSQL은 대부분 이 CAP 이론을 따르고 있다(<그림 1> 참조).

- Consistency는 분산된 노드 중 어느 노드로 접근하더라도 데이터 값이 같아야 한다는 기능적 특징이다(데이터 복제 중에 Query가 되면, Consistency를 제공하지 않는 시스템의 경우 다른 데이터 값이 Query 될 수 있다).
- Availability는 클러스터링된 노드 중 하나 이상의 노드가 FAIL이 되더라도, 정상적으로 요청을 처리할 수 있는 기능을 제공하는 특징이다.
- Partition Tolerance는 클러스터링 노드 간에 통신하는 네트워크가 장애를 겪더라도 정상적으로 서비스를 수행할 수 있는 기능이다.

그래서 NoSQL을 선택할 때는 이 CAP 이론을 이해하고 해당 NoSQL 제품이 CAP 중 어느 두 가지 특성을 가지고 있는지를 파악한 후에 업무 특성에 맞게 선택해야 한다.

NoSQL의 분류
NoSQL은 데이터 저장 구조에 따라 다음과 같이 크게 세 가지 분류로 정의될 수 있다.

● Key/Value Store
가장 기본적인 패턴으로 대부분의 NoSQL은 다른 데이터 모델을 지원하더라도, 기본적으로 Key/Value의 개념을 지원한다. Key/Value Store란 Unique한 Key에 하나의 Value를 가지고 있는 형태를 이야기한다. Put(Key,Value), Value := get(Key) 형태의 API로 접근한다.


<그림 2> Key Value Store 데이터 구조

Value는 String이나 Integer와 같은 Primitive 타입이 될 수도 있지만, 이 정도로는 우리가 일반적으로 사용하는 테이블 형태의 데이터를 저장할 수 없다. 이런 까닭에 조금 더 확장된 개념을 사용하는데, 그것이 바로 Column Family라는 개념이다. Key 안에 (Column, Value) 조합으로 된 여러 개의 필드를 갖는데 이를 Column Family라고 한다.


<그림 3> Column Family 기반의 데이터 구조

예를 들어, 사용자 프로필을 저장하는 시나리오가 있을 때 사용자의 이름을 KEY로 한다면 성별, 주소, 나이들은 각각의 Column이 될 수 있다. Key 필드는 RDBMS에서 Primary Key, Column 필드들은 RDBMS의 일반 데이터 필드로 이해하면 된다. 프로그래밍 언어와 비교해서 생각한다면 Key/Value Store는 Map 데이터 구조와 유사하다.
Oracle Coherence나 Redis와 같은 NoSQL이 이 데이터 모델을 기본 모델로 사용한다.

● Ordered Key/Value Store
Key/Value Store의 확장된 형태로 Key/Value Store와 데이터 저장 방식은 동일하나, 데이터가 내부적으로 Key 순서로 Sorting되어 저장된다.


<그림 4> Ordered Key/Value Store의 테이블 구조

Sorting이 대수롭지 않은 것 같지만, NoSQL 관점에서는 대단히 중요한 기능을 제공하게 된다. 뒤에 데이터 모델링 기법에서도 다루겠지만, NoSQL은 RDBMS의 Order By와 같은 기능을 제공하지 않기 때문에 결과값을 업데이트 날짜 등으로 Sorting해서 보여주는 것은 이 Ordered Key/Value Store가 절대적으로 유리하다. 대표적인 제품으로는 아파치(Apache)의 HBase, Cassandra 등이 있다.

● Document Key/Value Store
Key/Value Store의 확장된 형태로, 기본적으로는  Key/Value Store이다. Key에 해당하는 Value 필드에 데이터를 저장하는 구조는 같으나, 저장되는 Value의 데이터 타입이 Document라는 타입을 사용한다. Document 타입은 MS 워드와 같은 문서를 이야기하는 것이 아니라 XML, JSON, YAML과 같이 구조화된 데이터 타입으로, 복잡한 계층 구조를 표현할 수 있다. 


<그림 5> Document Store 기반의 테이블 구조

아울러 Document Store 기반의 NoSQL은 제품에 따라 다르기는 하지만 대부분 추가적인 기능(Sorting, Join, Grouping 등)을 제공한다. 대표적인 제품으로는 MongoDB, CouchDB, Riak 등이 있다.

그리고 여기서는 구체적으로 다루지 않지만 Graph나 Tree와 같은 데이터 구조를 저장하기 위해 최적화된 Neo4J 등의 NoSQL이 있다. 만약에 테이블 구조의 데이터가 아니라 Graph 구조의 데이터를 저장하고자 한다면 Neo4J를 한번 고려해보길 바란다.

NoSQL 제품별 선호도
NoSQL 영역에는 수많은 제품이 있기 때문에 어떤 제품을 고를지는 매우 어려운 문제로 다가온다. 제품 특성이 유사하다 하더라도 교육은 쉬운지, 기술 지원은 가능한지, 오픈소스일 경우 지속적인 유지 보수 등은 가능한지를 판단해야 하는데, 다른 솔루션 선정과 마찬가지로 가장 손쉬운 판단 방법은 많이 쓰는 NoSQL을 고려하는 것이다. 


<그림 6> Indeed.com의 구인자 분포 결과 분석을 통한 NoSQL 선호도

<그림 6>은 미국의 구인 사이트 자료를 토대로 작성한 각 NoSQL 제품별 구인자 수 변화 추이다.

<그림 6>에서 보면 MongoDB가 제일 높고, Cassandra나 HBase가 그 뒤를 따른다. 그 다음으로는 Redis가 있으며 기타 NoSQL 제품들(Voldmort, Riak, CouchDB) 등이 따른다. MongoDB의 경우 RDBMS적인 특성을 가지고 있어서 기존 RDBMS 기반의 개발자들이 쉽게 적응할 수 있고 HBase나 Cassandra의 경우 대용량 데이터 저장과 성능 면에서 조금 더 유리하기 때문에 이런 추이를 보이는 것으로 판단된다.

NoSQL과 기존 RDBMS와의 차이
NoSQL이 DBMS라고 생각해서 RDBMS와 같은, 또는 떨어지지만 유사한 기능을 제공할 것이라고 생각하면 큰 오산이다. NoSQL은 데이터를 저장한다. 그리고 Key에 대한 Put/Get만 지원한다. RDBMS로 치면 다음과 같이만 딱 지원한다.

Put : Insert into TABLE VALUES(KEY,value1,value2,…,valuen)
Get : Select * from TABLE where KEY=”key”

물론 제품에 따라서 기능에 대한 지원 범위가 다르긴 하지만, 공통적으로 고민해야 하는 기능은 다음과 같다.

- Sorting (SQL의 Order By)
- Join (RDBMS에서 2개의 Table을 Foreign Key를 이용해 join)
- Grouping (SQL 문의 group by)
- Range Query (where key>“start” and key<“end”와 같이 일정 범위 내의 내용을 쿼리해오는 기능)
- Index (RDBMS에 Index를 지정해 select query 성능을 높이는 기능)

RDBMS에서는 너무나도 익숙하게 사용했던 기능들이기 때문에, 막상 이 기능들을 빼고 데이터를 다루고자 하면 매우 불편하다. 여기서는 이러한 기능들을 ‘NoSQL 데이터 모델링 패턴’ 소개를 통해 NoSQL에서 어떻게 구현할 수 있는지 알아볼 것이다.

NoSQL 사용시 주의할 점
NoSQL이 나온 지 수년이 지나긴 했지만, 특히 국내에서는 아직까지 NoSQL에 대한 경험이 매우 적은 편이다. 또한 NoSQL이라는 이름으로만 묶여 있지, 각 제품군에 따른 특성이 매우 다르기 때문에 특정 제품의 경험을 다른 제품에 적용하기도 매우 어렵다. 그럼에도 불구하고 최신 기술이라는 이름과 빅데이터라는 패러다임에 묶여 많이 검토되고 있는 게 지금의 상황이다. 그럼 NoSQL을 사용할 때 주의해야 할 점은 무엇일까?

● 과연 NoSQL이 필요한가?
먼저 NoSQL이 정말로 필요한지를 판단해야 한다. NoSQL이라는 새로운 기술과 제품군을 사용하려면, 그에 들어가는 교육과 개발 비용들이 결코 만만치 않다. 기존의 Oracle이나 MySQL과 같은 RDBMS를 사용해도 국내 대부분의 서비스는 구현이 가능하다. 데이터가 늘어나면 추가 RDBMS 클러스터를 추가해 용량을 증설하는 방법도 있다(카카오톡의 경우 MySQL을 사용해 서비스하고 있으며 여러 MySQL 인스턴스에 데이터를 분산해 저장하는 형태를 사용한다).

물론 여러 RDBMS에 걸쳐서 데이터를 저장하는 것보다는 NoSQL 클러스터 하나만 사용하는 것이 운영 등에 있어서 효율적이기는 하지만, 그만큼 만만하지 않다는 것이다. 

과연 현재 업무에 NoSQL이 적절한지 그리고 그 정도의 데이터 용량이 필요한지 판단해 볼 필요가 있다. 벤처에서 1억 명을 대상으로 한 서비스를 만들려고 시도할 때 NoSQL이 적합해 보이지만, NoSQL을 공부하는 데 시간이 들어가고 운영하면서 수많은 장애를 겪다 보면 사용자들은 다 떨어나갈지도 모른다. MySQL 등 기존의 익숙한 기술을 사용하다가 MySQL로 도저히 용량 감당이 되지 않을 경우에 NoSQL로의 전환을 고려하는 것은 어떨까? MySQL로 용량이 안 된다면 그때는 이미 사업이 성공했을 때이므로, NoSQL로 전환할 기술력이나 자금력도 충분할 것이다(실제로 페이스북도 MySQL로 서비스하다가 수년 전에 Cassandra로 전환했다).

● 적절한 NoSQL 제품군의 선정
앞서도 설명했지만, NoSQL은 RDBMS가 아닌 것의 약자이다. 즉 RDBMS만 아니면 모두 NoSQL이기 때문에 그 특성이 매우 다양하다. 따라서 각 NoSQL의 특성을 잘 파악하고 업무와 팀의 특성에 맞는 제품을 선정하는 것이 첫걸음인 셈이다.

예를 들어 Riak의 경우 기술 지원이 가능하며 2nd Index 및 Full Text Search가 지원된다. MongoDB의 경우에는 RDBMS와 유사한 기능을 가지고 있으므로 사용이 매우 편리하지만, 반대로 타 NoSQL에 비해 용량적인 한계를 갖는다. 

Cassandra의 경우, 구조적인 특성상 쓰기 성능(Write Performance)이 매우 우수하다. 이외에도 데이터가 Sorting이 되는지, Consistency 적용은 어떻게 되는지 등에 대해 이해한 후에 알맞은 NoSQL을 선택해야 한다.

● 데이터 모델링
NoSQL은 기본적으로 RDBMS와 다르다. 데이터 저장 방식도 다르고 기능도 부족하기 때문에, RDBMS처럼 데이터 모델링을 하면 100% 성능 문제가 생길 수밖에 없다.

RDBMS가 데이터 모델링에서부터 시작해서 정규화를 통해(중복 제거) 테이블을 만들어내고, 해당 테이블을 통해 쿼리를 수행해 결과를 뽑아낸다고 하면, NoSQL은 이와 정반대의 접근이 필요하다. 먼저 수행할 쿼리를 정의하고 이에 맞춰 데이터 테이블을 정의하고, 성능을 높이기 위해 일부로 중복을 허용해 테이블을 정의해야 한다.

사실상 NoSQL은 이 데이터 모델링이 설계의 90%라고 봐도 된다. NoSQL의 데이터 모델링에 대해서는 이어지는 2부에서 자세히 설명하기로 하겠다.

● RDBMS와 적절한 혼합
NoSQL은 데이터를 저장하기는 하지만, 복잡한 데이터 저장이나 쿼리에는 한 없이 부족하다. 대용량 데이터를 빠르게 저장 및 쿼리하는 데 최적화된 기술이지만, 서비스 시스템에는 당연히 복잡한 데이터도 있고 관계 정의가 필요한 경우도 있다. NoSQL을 사용할 때는 모든 데이터를 NoSQL에 저장할 생각을 하는 것보다는 인덱스성 데이터나 복잡한 쿼리가 필요한 데이터는 RDBMS에 저장하고, 실제 데이터 등을 NoSQL에 저장함으로써 RDBMS와 NoSQL을 적절하게 혼합해 사용토록 설계하는 것이 좋다.

● 하드웨어 설계 병행
NoSQL을 사용할 때는 처음부터 하드웨어 설계를 병행하는 것이 좋다. 디스크 RAID 구성은 할 것인지 말 것인지, 한다면 어떤 RAID 구성을 할 것인지 등을 고려한다. 

그리고 NIC, 데이터 트래픽을 위한 부분과 관리(management)를 위한 부분을 물리적으로 분리하는 것이 좋으며, 대역폭은 1G를 사용할 것인지 10G를 사용할 것인지도 결정해야 한다. 또한 물리적인 디스크 수에 따라 성능 변화가 많은 만큼 같은 용량이라도 몇 개의 디스크를 사용할 것인지 등에 대해서도 고민해야 한다. 따라서 NoSQL 제품을 결정하고 하드웨어를 도입하기 전에 레퍼런스를 충분히 검토하고 PoC(Proof of Concept)를 거쳐야 한다.

● 운영 및 백업
RDBMS를 운영하면 DBA가 당연히 따라 붙는다. NoSQL도 DB인 만큼, 당연히 운영과 관리를 위해 administrator가 필요하다. 일반적인 WAS(톰캣과 같은 웹서버)에 비해 복잡도가 훨씬 높고 분산되어 있으며 하드웨어까지 함께 관리 및 관제해야 하기 때문에 반드시 전문적인 administrator가 있어야 하며, 시스템에 대한 체계적인 모니터링 방안 등의 운영 체계가 수립돼야 한다.

특히 NoSQL의 용량을 증설할 때는 단순히 서버만 증설해서 되는 제품도 있지만, 대부분은 기존 서버에 새로운 서버를 포함해서 데이터를 재분배시키는 등의 작업이 필요하다. 이러한 작업은 철저한 사전 연습과 경험이 없으면 운영 과정에서 데이터를 유실할 우려가 있으므로 증설에 대한 운영 정책을 가지고 있어야 한다. 

NoSQL이 분산 및 복제 구조를 통해 데이터의 안정성을 보장하지만 앞에서 언급한 바와 같이 운영상의 실수 또는 데이터센터 자체의 장애(특히 클라우드 사용시)로 데이터가 유실되는 경우가 발생할 수 있으므로 백업에 대한 방안도 똑같이 고려돼야 한다.

지금까지 NoSQL에 대한 개념과 특징 등을 설명했다. NoSQL은 대용량의 데이터를 빠르고 안전하게 저장할 수 있다는 점에서 분명히 훌륭한 기술이기도 하지만, 그만큼 기술적인 난이도가 높고 다루기가 쉽지 않다. NoSQL은 절대 ‘은탄환(Silver Bullet)’과 같은 특효약이 아니다. 반드시 제대로 된 이해와 철저한 준비가 있어야만 사용할 수 있는 기술이다.

이어지는 글에서는 NoSQL에서 가장 중요한 데이터 모델링 기법을 소개하고, 대표적인 NoSQL 제품들을 하나하나 살펴보기로 한다.


출처 - http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=42440





'DB > NoSQL' 카테고리의 다른 글

nosql - 개념 설명  (0) 2013.04.29
nosql - reference site  (0) 2013.04.29
nosql - 주의 사항  (0) 2013.04.29
nosql - list  (0) 2013.04.29
NoSQL - 데이타 모델링  (0) 2013.04.29
Posted by linuxism
,