[NoSQL: 빅 데이터 세상으로 떠나는 간결한 안내서] 3장. 데이터 모델 상세
요점
- 집합 지향 데이터베이스에서는 집합 내 관계보다 집합 간 관계를 처리하는 것이 더 어렵다.
- 그래프 데이터베이스는 데이터를 노드와 간선의 그래프 구조로 만들며,
복잡한 관계를 가지는 데이터에 최적이다.
- 무스키마 데이터베이스는 레코드에 필드를 자유롭게 추가할 수 있지만,
보통 데이터 사용자가 기대하는 암묵적 스키마가 있다.
- 집합 지향 데이터베이스는 주요 집합과 구조가 다른 데이터 제공을 위해 구체화 뷰를 사용한다.
구체화 뷰를 만드는 작업은 보통 맵-리듀스 계산을 통해 수행된다.
3.1 관계
집합은 함께 접근하는 데이터를 한 덩어리로 모아놓기 때문에 유용
하지만, 관련 데이터에 다르게 접근하는 경우도 많음
ex) 고객과 주문의 관계
고객 정보에 접근할 때마다 그 고객의 주문 내역까지 함께 접근하고 싶음
집합 모델 : 고객과 주문 내역을 하나의 집합으로 묶어 둠
하지만, 다른 애플리케이션에서 주문을 개별로 처리하길 원하여 주문을 독립된 집합으로 모델링하길 원함
가장 간단한 방법은 주문에 대한 집합 데이터에 고객 아이디를 포함시키는 것
데이터베이스는 고객-주문 관계를 알지 못하지만, 알게된다면 유용할 것
이 결과 많은 데이터베이스가 이런 관계를 데이터베이스에 보이도록 하는 방법을 제공함.
문서 저장소 : 집합의 내용을 가지고 데이터베이스가 인덱스를 만들고 조회할 수 있게 한다.
키-값 저장소 중 하나인 리악은 부분 검색과 링크 순회를 지원하도록 메타데이터에 링크 정보를 설정 가능
하지만 집합 지향 데이터베이스에서는 여러 집합에 걸쳐 데이터를 조작해야 하는 경우 처리가 불편해짐
이를 처리하는 방법은 이 장 뒷부분에서 설명하지만 기본적인 불편함은 그대로 남음.
데이터 사이에 많은 관계가 있다면 NoSQL 저장소보다는 관계형 데이터베이스 사용이 나을수도 있지만, 또 관계형 데이터베이스도 복잡한 관계를 처리하는 데 아주 뛰어나지는 않다는 점을 기억할 필요가 있음.
이럴때 다른 종료의 데이터베이스를 도입할 좋은 시기다.
3.2 그래프 데이터베이스
그래프 데이터베이스는 관게형 데이터베이스에 대한 다른 종류의 불만으로부터 시작됨
그래프란 데이터 구조에 나오는 노드가 간선으로 연결된 그래프를 뜻함.
위와 같은 구조에서는 "내 친구가 좋아하는 사람이 쓴 데이터베이스 분야의 책은?" 같은 질문을 할 수 있다.
그래프 데이터베이스는 소셜 네트워크나 제품 선호도, 자격 규정 같은 복잡한 관계를 이루는 데이터를 다루는데 이상적이다.
그래프 데이터베이스는 구조가 단순하다. 간선과 노드가 전부다.
이런 본질적 특성 외에 많은 변형 데이터 모델이 있다.
플록DB(FlockDB) : 단순한 노드와 간선 이외에 다른 속성을 지원하지 않는다.
네오4J(Neo4J) : 스키마가 없는 방식으로 노드나 간선의 속성에 자바 객체를 추가할 수 있다.
인피니트 그래프(Infinite Graph) : 내장 타입의 서브클래스로 된 사용자의 자바 객체를 노드와 간선으로 저장한다.
그래프 데이터베이스에서 관계를 따라가는 연산은, 관계형 데이터베이스에서의 조인보다 비용이 적다.
그래프 데이터베이스에서는 관계 사이를 돌아다니는 작업의 대부분을 쿼리 시점에서 입력시점으로 옮겼기 때문이다.
"안나와 바바라 두 사람 모두가 좋아하는 것을 전부 찾으라." 같은 쿼리를 처리하려면 간선의 네트워크를 돌아다니며 데이터를 찾아야 한다. 그러나 시작점이 필요하므로, 보통 일부 노드는 아이디 같은 속성으로 인덱스를 달 수 있다.
따라서 아이디를 검색(즉, '안나'와 '바바라'란 이름의 사람을 검색)한 다음, 간선을 이용할 수 있다.
3.3 스키마 없는 데이터베이스
NoSQL 데이터베이스에서는 데이터를 저장하는 것이 자유롭다.
무스키마 저장소에서는 변경을 처리하는 것도 쉽지만, 균일하지 않은 데이터(각 레코드가 서로 다른 집합의 필드를 가지는 데이터)를 처리하는 것 역시 쉬워진다.
(관계형 데이터베이스를 예시로 들면 nullable 필드를 만들지 않아도 된다.)
무스키마의 단점
fieldName: value 목록을 리포트에 표시하는 게 전부라면 스키마는 방해만 된다.
그러나 보통은 데이터로 더 복잡한 작업을 수행한다.
데이터에 접급하는 프로그램은 거의 항상 어떤 형태든 암묵적 스키마에 의존한다는 점이다.
암묵적 스키마를 갖는 다는 것은 어떤 데이터가 있는지 확인하려면 코드를 파봐야 한다는 뜻이다.
스키마 정보를 활용해 효율적으로 데이터를 저장하고 꺼낼 수 없다.
또 여러 애플리케이션이 데이터를 비일관적으로 조작하지 않는지 확인하기 위한 데이터 유효성 검사도 할 수 없다.
무스키마 데이터베이스를 활용하면 스키마가 데이터베이스에서 애플리케이션 코드로 이동한다.
여러 팀이 개발하는 많은 애플리케이션이 한 데이터베이스에 접근하는 경우라면 문제가 생기는데,
몇 가지 방법으로 완화할 수 있다.
1. 모든 데이터베이스 상호작용을 단일 애플리케이션에서 캡슐화하고 다른 애플리케이션과는 웹 서비스로 통합
2. 각 애플리케이션에서 접근하는 집합 구조 영역에 대해 명확하게 기술
무스키마는 데이터베이스 구조를 변경할 때 특히 균일한 데이터일 경우 큰 영향을 받는다.
관계형 데이터베이스와 마찬가지로 데이터를 저장하는 방식을 바꿀 때도 예전 데이터와 새로운 데이터에 모두 쉽게 전근할 수 있도록 통제하는 연습이 필요하다.
또 무스키마의 융통성은 한 집합 구조 내에서만 유효하다는 점을 알아야 한다.
3.4 구체화 뷰
집합 지향 데이터 모델은 한 집합에 모든 정보를 포함시켜 한번에 저장하거나 읽어오기 좋은 점을 앞서 설명했다.
그러나 그에 상응하는 단점도 있다.
제품 관리자가 특정 상품이 지난 2주간 얼마나 팔렸는지 알고 싶어 한다면 어떻게 될까?
이 질문에 답하려면 모든 데이터를 읽어야 할 수도 있어, 집합 지향은 불리하다.
관계형 데이터베이스는 뷰를 통해 데이터를 저장되어 있는 것과 다른 형태로 쉽게 볼 수 있다.
뷰를 사용하면 데이터가 유도된 데이터인지, 원래 데이터인지 클라이언트에 숨길 수 있다. 물론 비용이 비싸다.
이를 보완하려고 계산 결과를 미리 만들어 디스크에 캐시해 놓는 구체화 뷰(materialized view)가 고안되었다.
NoSQL 데이터베이스에 뷰는 없지만, 쿼리 결과를 미리 계산해 캐시해 놓을 수 있다.
이를 '구체화 뷰'란 용어를 그대로 쓴다
구체화 뷰를 만드는 방법 두가지
1) 기본 데이터가 바뀔 때 구체화 뷰도 함께 바뀌도록 하는 방법
- 주문을 추가하면 각 제품에 대한 구매 내역 집합도 함께 업데이트 됨
- 쓰기보다 읽기가 훨씬 많고, 구체화 뷰가 최신 데이터를 갖도록 함
- 단점) 업데이트할 때마다 오버헤드가 발생
2) 데이터를 읽어 뷰를 계싼하고 결과를 데이터베이스에 저장하는 방식
- 수행해야 할 계산을 제공하면 설정된 파라미터에 따라 필요할 때 데이터베이스가 계산을 실행
- 점증적 맵-리듀스 이용시 편리
구체화 뷰는 동일한 집합에 대해서도 사용 가능
- 주문 문서는 주문에 대한 요약 정보를 제공하는 주문 요약 요소를 포함하고 있어 주문 요약에 대한 쿼리가 주문 문서 전체를 넘겨주지 않아도 됨
- 서로 다른 칼럼 패밀리르 이용해 구체화 뷰를 만드는 것은 칼럼 패밀리 데이터베이스에서 흔히 사용되는 방법
3.5 데이터 접근을 위한 모델링 (실습)
데이터 집합 모델을 만들 때는 이 집합과 관계된 데이터에 대한 부수효과가 무엇인지뿐 아니라 데이터를 어떻게 읽을 것인지도 고려해야한다.
고객에 대한 모든 데이터를 키-값 저장소에 저장했을 경우
- 키를 사용해 고객 정보 및 관련 데이터를 읽을 수 있음
- 주문 또는 각 주문에서 판매된 상품을 읽어야 한다면 객체 전체를 읽고, 클라이언트에서 분석해 결과를 만들어야함
- 참조가 필요한 경우라면 값 객체를 Customer와 Order 객체로 분리해 서로에 대한 참조를 유지하도록 키-값 저장소의 데이터를 변경하거나 저장소를 문서 저장소로 바꿔 문서 내부를 쿼리할 수 있다.
참조를 사용하면 (그림3.3),고객 데이터와 독립적으로 주문 데이터를 찾을 수 있게 되고, Customer에 있는 orderId 참조를 통해 Customer에 대한 모든 Orders를 찾을 수 있다.
읽기에는 최적화 되지만, 새로운 Order가 생길 때마다 Customer에 orderId 참조를 넣어주어야 한다.
집합은 분석 데이터를 얻는 데도 사용할 수 있다.
ex) 집합을 업데이트할때 주어진 제품이어느 주문에 포함되어있는지에 대한 정보. 즉 고객이 주문을 할 때마다 다음 형태의 데이터를 채울 수 있다.
이렇게 역정규화하면관심 데이터에 빠르게 접근할 수 있게 된다.
일일 배치 작업이 데이터 웨어하우스 테이블에 결과를 기록하고 분석 결과를 생성할 때까지 기다릴 필요가 없다.
이를 실시간 BI(Business Intelligence) 또는 실시간 분석의 기반이 된다.
칼럼 패밀리 저장소에서 사용할 모델을 만들 때는 칼럼 순서를 조정해 자주 사용되는 칼럼을 먼저 읽도록 할 수 있다.
칼럼 패밀리를 사용해 데이터 모델을 만들 때는 쓰기(wrtie, update) 편의성보다는 쿼리 요건에 맞춰야 한다.
일반적인 큐칙은 쿼리를 쉽게 하고 쓰기 시 데이터를 역정규화 하는것이다.
데이터 모델을 만드는 방법
1) Customer와 Order를 다른 칼럼 패밀리로 저장하는 것(그림 3.4)
- 고객의 모든 주문에 대한 참조는 Customer 칼럼 패밀리에 있다.
- 이와 같은 역정규화를 통해 쿼리(읽기) 성능을 높일 수 있다.
똑같은 데이터를 그래프 데이터베이스로 만들 때는, 모든 객체를 노드로만들고 객체 간 관계를 노드 간 관계로 모델링한다.
이 관계에서는 타입과 방향성이 중요하다.
각 노드는 다른 노드와 독립적 관계를 가지며, 관계는 PURCHASED, PAID_WITH 등 같은 이름이 붙는다. (그림 3.5)
이 관계 이름을 통해 그래프를 순회할 수 있다.
'리팩터링 데이터베이스'란 상품을 구매(PURCHASED)한 모든 고객을 찾고 싶다면, '리팩터링 데이터베이스' 제품 노드를 조회한 다음 PURCHASED 관계를 가진 모든 Customer를 찾으면 된다.