# Chapter 2: 데이터 모델과 질의 언어

<br>

## 💡 책에서 기억하고 싶은 내용

<br>

* 대부분의 애플리케이션은 하나의 데이터 모델을 다른 데이터 모델 위에 계층을 둬서 만든다
  * 각 계층의 핵심적인 문제는 다음 하위 계층 관점에서 데이터 모델을 `표현` 하는 방법이다
* 복잡한 애플리케이션에서는 여러 API를 기반으로 만든 API처럼 중간 단계를 더 둘 수 있지만, 기본 개념은 여전히 동일하다
  * 각 계층은 `명확한 데이터 모델을 제공` 해 하위 계층의 `복잡성을 숨긴다`
* 데이터 모델은 그 위에서 소프트웨어가 할 수 있는 일과 할 수 없는 일에 지대한 영향을 주므로 `애플리케이션에 적합한 데이터 모델` 을 선택하는 작업은 상당히 중요하다

## 관계형 모델과 문서 모델

* 관계형 모델의 목표는 `정리된 인터페이스` 뒤로 `구현 세부 사항` 을 `숨기는 것` 이다

### NoSQL의 탄생

* NoSQL 데이터베이스를 채택한 데는 다음과 같은 다양한 원동력이 있다
  * `대규모 데이터셋` 이나 매우 `높은 쓰기 처리량` 달성을 관계형 데이터베이스보다 쉽게 할 수 있는 뛰어난 `확정성`의 필요
  * 상용 데이터베이스 제품보다 무료 오픈소스 소프트웨어에 대한 선호도 확산 …
  * 관계형 모델에서 지원하지 않는 특수 질의 동작
  * 관계형 스키마의 제한에 대한 불만과 더욱 `동적` 이고 `표현력` 이 풍부한 데이터 모델에 대한 바람
* 애플리케이션은 저마다 요구사항이 다르다
  * 한 사용 사례에 맞는 최적의 기술 선택은 또 다른 사용 사례에 맞는 최적의 선택과는 다를 수 있다
  * 그러므로, 가까운 미래에는 관계형 데이터베이스가 폭넓은 다양함을 가진 비관계형 데이터스토어와 `함께 사용` 될 것이다
    * 이런 개념을 `다중 저장소 지속성 (polyglot persistence)` 라 한다

### 객체 관계형 불일치

* 객체지향 프로그래밍 언어로 개발된 애플리케이션에서 데이터를 관계형 테이블에 저장하려면, 애플리케이션 코드와 데이터 베이스 모델 객체 (Table, Low, Column) 사이에 거추장스러운 `전환 계층` 이 필요하다
  * 이런 모델 사이의 분리를 `임피던스 불일치 (impedance mismatch)` 라고 부른다
* `객체 관계형 매핑 (ORM) 프레임워크` 는 전환 계층에 필요한 boilerplate code의 양을 줄이지만, 두 모델 간의 차이를 완벽히 숨길 수 없다
* `JSON` 표현은 다중 테이블 (multi-table) schema 보다 더 나은 지역성(locality) 을 갖는다

### 다대일과 다대다 관계

* `드롭다운 리스트`나 `자동 완성 기능`을 만들어 `사용자가 선택`하게 하는 데의 장점
  * 프로필 간 일관된 스타일과 철자
  * 모호함 회피
  * 갱신의 편의성
  * 현지화 지원
  * 더 나은 검색
* 정보가 중복돼 있으면 모든 중복 항목을 변경해야 한다
  * 이것은 `쓰기 오버헤드`와 `불일치`(정보의 일부 중복은 갱신됐지만 다른 중복 항목이 갱신되지 않음) 위험이 있다
  * 이런 중복을 제거하는 일이 데이터베이스의 정규화 이면에 놓인 핵심 개념이다
* 중복된 데이터를 정규화하려면 `다대일(many-to-one)` 관계가 필요한데, 다대일 관계는 `문서 모델`에 적합하지 않다
  * 관계형 데이터베이스에서는 조인이 쉽기 때문에 ID로 다른 테이블의 로우를 참조하는 방식은 일반적이다
  * 문서 데이터베이스에서는 일대다 트리 구조를 위해 조인이 필요하지 않지만 조인 에 대한 지원이 보통 약하다 ⭐
    * 데이터베이스 자체가 조인을 지원하지 않으면, 데이터베이스에 대한 `다중 질의`를 만들어서 애플리케이션 코드에서 조인을 흉내 내야 한다

## 문서 데이터베이스는 역사를 반복하고 있나?

* 문서 데이터베이스처럼 IMS도 일대다 관계에서는 잘 동작한다. 하지만 다대다 관계 표현은 어려웠 고 조인은 지원하지 않았다
  * 개발자는 (비정규화된) 데이터를 중복할지 한 레코드와 또 다른 레코드의 참조를 수동으로 해결할지 결정해야 했다
  * 1960년대와 70년대의 이 문제는 오늘날 문서 데이터 베이스를 사용해서 작업 중인 개발자가 풀어야 할 문제와 매우 비슷하다
* 계층 모델의 한계를 해결하기 위해 다양한 해결책이 제안됐다
  * 가장 두드러지는 해결책 두 가지
    * `네트워크 모델` (초기에는 많은 신봉자들이 있었지만 결국 희미하게 잊혀졌다)
      * 수동 접근 경로 선택은 1970년대에는 (탐색이 매우 느린 테이프 드라이브와 같이) 매우 제한된 하드웨어 성능을 가장 효율적으로 사용할 수 있었지만,
      * 데이터베이스 `질의와 갱신을 위한 코드`가 `복잡`하고 `유연하지 못한` 문제가 있었다
    * `관계형 모델`(SQL이 되어 세상을 지배했다)
      * 관계형 모델이 하는 일은 알려진 모든 데이터를 배치하는 것
      * 관계형 데이터베이스에서 `질의 최적화기(query optimizer)` 는 질의의 어느 부분을 `어떤 순서로 실행할지`를 결정하고, 사용할 `색인을 자동으로 결정`한다
      * 접근 경로를 애플리케이션 개발자가 아니라 질의 최적화기가 자동으로 만든다는 차이점이 있다
        * 그래서 접근 경로를 따로 생각할 필요가 없다!

### 문서 데이터베이스와의 비교

* 문서 데이터베이스는 한 가지 측면에서 계층 모델로 되돌아갔다
  * 문서 데이터베이스는 별도 테이블이 아닌 상위 레코드 내에 `중첩된 레코드` 를 저장한다
  * 하지만 다대일과 다대다 관계를 표현할 때 관계형 데이터베이스와 문서 데이터베이스는 근본적으로 다르지 않다
    * 둘 다 관련 항목은 `고유한 식별자` 로 `참조` 한다
      * 관계형 모델에서는 `외래 키` 라 부르고,
      * 문서 모델에서는 `문서 참조 (document reference)` 라 부른다

## 관계형 데이터베이스와 오늘날의 문서 데이터베이스

* 관계형 데이터베이스와 문서 데이터베이스를 비교하는 경우 `내결함성`과 `동시성 처리`를 포함해 고려해야 할 차이점이 많이 있다
  * 해당 장에서는 `데이터 모델의 차이`에만 집중한다!
* `문서 데이터 모델` 을 선호하는 주요 이유는 스키마 `유연성` , `지역성` 에 기인한 `더 나은 성능` 때문이고, 일부 애플리케이션의 경우 애플리케이션에서 사용하는 데이터 구조와 더 가깝기 때문이다
  * `관계형 모델`은 `조인`, `다대일`, `다대다` 관계를 더 잘 지원함으로써 문서 데이터 모델에 대항한다

### 어떤 데이터 모델이 애플리케이션 코드를 더 간단하게 할까?

* 애플리케이션에서 데이터가 `문서와 비슷한 구조`(`일대다 관계 트리`로 보통 `한 번에 전체 트리 를적재`)라면 `문서 모델`을 사용하는 것이 좋다
  * 문서와 비슷한 구조를 여러 테이블로 `나누어 찢는(shredding)` 관계형 기법은 다루기 힘든 스키마와 불필요하게 복잡한 애플리케이션 코드를 발생시킨다
* `문서 모델` 은 문서 내 중첩 항목을 바로 참조할 수 없지만, 문서가 너무 깊게 중첩되지 않으면 일반적으로 문제가 되지 않는다
* 애플리케이션에서 다대다 관계를 사용한다면 문서 모델은 매력이 떨어진다
  * `비정규화` 로 조인의 필요성 줄이기가 가능하지먄, 애플리케이션 코드는 비정규화된 데이터의 `일관성`을 유지하기 위해 추가 작업을 해야한다
  * 조인은 애플리케이션 코드에서 데이터베이스에 다중 요청을 만들어 흉내 낼 수 있지만, `복잡도`가 애플리케이션으로 이동할 뿐만 아니라 보통 데이터베이스 내 특화된 코드로 수행되는 조인보다 더 `느리다` ⭐
    * 이런 경우에 문서 모델을 사용하는 것은 훨씬 더 복잡한 애플리케이 션 코드와 나쁜 성능으로 이어질 수 있다
* `상호 연결`이 많은 데이터의 경우
  * 문서 모델은 곤란 하지만
  * 관계형 모델은 무난하며
  * 그래프 모델은 매우 자연스럽다

### 문서 모델에서의 스키마 유연성

* 대부분의 문서 데이터베이스와 관계형 데이터베이스에서 지원하는 JSON은 문서의 데이터에 어떤 스키마를 강요하지 않는다
  * 스키마가 없다는 뜻은 `임의의 키와 값`을 `문서에 추가`할수 있고 읽을 때 클라이언트는 문서에 포함된 `필드`의 `존재 여부`를 `보장하지 않는다`는 의미다
* 문서 데이터베이스는 `읽기 스키마 (schema-on-read)` 이다
  * 즉, 데이터 구조는 암묵적이고 데이터를 읽을 때만 해석된다
* 스키마 변경은 느리고 중단시간을 요구하기 때문에 평판이 나쁘다
  * 대부분의 관계형 데이터베이스 시스템은 ALTER TABLE 문을 수 밀리초 안에 수행한다
  * but, MySQL은 `ALTER TABLE` 시에 전체 테이블을 복사한다
    * 이는 큰 테이블을 변경할 때 수 분에서 수 시간까지 중단 시간이 발생한다는 의미다
* 읽기 스키마 접근 방식은 컬렉션 안의 항목이 어떤 이유로 모두 `동일한 구조가 아닐 때`(즉 데이터가 여러다른 유형으로구성돼있음) 유리하다
  * why?
    * 다른 여러 유형의 오브젝트가 있고, 각 유형의 오브젝트별로 자체 테이블에 넣는 방법은 실용적이지 않다
    * 사용자가 제어할 수 없고 언제나 변경 가능한 외부 시스템에 의해 데이터 구조가 결정된다

### 질의를 위한 데이터 지역성

* 자주 전체 문서에 접근해야 할 때 `저장소 지역성 (storage locality)` 을 활용하면 성능 이점이 있다

### 문서 데이터베이스와 관계형 데이터베이스의 통합

* 관계형 데이터베이스와 문서 데이터베이스는 시간이 지남에 따라 점점 더 비슷해지고 있다
* 각 데이터 모델이 서로 부족한 부분을 보완해 나가고 있기 때문이다

## 데이터를 위한 질의 언어

* SQL은 선언형 질의 언어인 반면 IMS와 코다실은 명령형 코드를 사용해 데이터베이스에 질의한다
* 명령형 언어는 특정 순서로 특정 연산을 수행하게끔 컴퓨터에게 지시한다
* SQL이나 관계 대수 같은 `선언형 질의 언어`에서는 목표를 달성하기 위한 방법이 아니라 알고자 하 는 데이터의 패턴, 즉 결과가 충족해야 하는 조건과 데이터를 어떻게 변환(예를 들어 정렬, 그룹화, 집계) 할지를 지정하면 된다
* `선언형 질의 언어`는 일반적으로 명령형 API보다 더 간결하고 쉽게 작업할 수 있기 때문에 매력적이다
  * 하지만 더 중요한 점은 데이터베이스 엔진의 상세 구현이 숨겨져 있어 질의를 변경하지 않고도 데이터베이스 시스템의 성능을 향상시킬 수 있다는 점이다

### 웹에서의 선언형 질의

* 웹 브라우저에서 선언형 CSS 스타일을 사용하는 편이 자바스크립트에서 명령형으로 스타일을 다루기보다 훨씬 낫다
* 마찬가지로 데이터베이스에서는 SQL 같은 선언형 질의 언어가 명령형 질의 API보다 훨씬 좋다고 나타났다

### 맵리듀스 질의

* 맵리듀스(MapReduce)는 `많은 컴퓨터`에서 `대량의 데이터`를 처리하기 위한 `프로그래밍 모델`로, 구글에 의해 널리 알려졌다
* 몽고DB와 카우치DB를 포함한 일부 NoSQL 데이터 저장소는 `제한된 형태의 맵리듀스`를 지원한다
  * 이 메커니즘은 `많은 문서`를 대상으로 `읽기 전용(read-only) 질의`를 수행할 때 사용한다
* 맵리듀스는 선언형 질의 언어도 완전한 명령형 질의 API도 아닌 그 중간 정도에 있다
  * 질의 로직은 처리 프레임워크가 반복적으로 호출하는 `조각 코드`로 표현한다
  * 맵리듀스는 여러 함수형 프로그래밍 언어에 있는 `map`(collect라고도 함)과 `reduce`(fold나 inject라고도 함) 함수를 기반으로 한다
* 몽고DB의 `map` 과 `reduce` 함수는 수행할 때의 `제약 사항` - 두 함수는 `순수 함수`여야 한다
  * 즉, 입력으로 전달된 데이터만 사용하고, 추가적인 데이터베이스 질의를 수행할 수 없어야 하며, `부수 효과 (side effect)` 가 없어야 한다
  * 이런 제약 사항 때문에 데이터베이스가 `임의 순서`로 어디서나 이 함수를 실행할 수 있고, 장애가 발생해도 함수를 `재실행`할 수 있다
* 문자열을 `파싱` 하고, 라이브러리 함수를 `호출` 하고, `계산` 을 실행하는 등의 작업을 map과 reduce 함수에서 할 수 있다
* `클러스터 환경`에서 `분산 실행`을 위한 프로그래밍 모델인 맵리듀스는 상당히 `저수준 프로그래밍 모델` 이다
  * SQL 같은 고수준 질의 언어도 맵리듀스 연산의 파이프라인으로 구현할 수 있찌만, 맵리듀스를 사용하지 않은 분산 SQL 구현도 많다
  * SQL에 단일 장비에서 수행되도록 제한하는 것은 없으며, 맵리듀스가 분산 질의 실행에 대한 독점권을 갖는 것도 아니다

## 그래프형 데이터 모델

* 애플리케이션이 주로 일대다 (1:N) 관계이거나 레코드 간 관계가 없다면 `문서 모델` 이 적합하다
  * but, 데이터에서 다대다 (N:M) 관계가 매우 일반적일때는 관계형 모델이 단순한 다대다 관계를 다룰 수는 있지만, `데이터 간 연결`이 `복잡`해지면 `그래프`로 데이터를 모델링하기 시작하는 편이 더 자연스럽다
* 그래프는 `정점(vertex)` 과 `간선(edge)` 두 유형의 객체로 이루어진다
  * 정점을 노드나 엔티티 라고도 하고,
  * 간선을 관계나 호(arc) 라고도 한다
* 그래프로 모델링 할 수 있는 데이터 `예시`
  * 소셜 그래프
    * 정점은 사람이고, 간선은 사람들이 서로 알고 있음을 나타낸다
  * 웹 그래프
    * 정점은 웹 페이지고, 간선은 다른 페이지에 대한 HTML 링크를 나타낸다
  * 도로나 철도 네트워크
    * 정점은 교차로이고, 간선은 교차로 간 철로 선을 나타낸다
* 위의 예시에서 그래프의 정점은 모두 같은 유형 (사람이나 웹 페이지, 도로 교차로)을 나타낸다
  * but, 그래프는 이런 `동종 데이터`에 국한되지 않는다
  * 그래프를 동종 데이터와 마찬가지 방식으로 사용하면, 단일 데이터 저장소에 완전히 `다른 유형의 객체`를 `일관성 있게 저장`할 수 있는 방법을 제공한다
    * ex)
      * 페이스북은 여러 다른 유형의 정점과 간선을 `단일 그래프` 로 유지한다
      * 정점은 사람, 장소, 이벤트, 체크인, 사용자가 작성한 코멘트를 나타낸다
      * 간선은 어떤 사람이 서로 친구인지, 누가 어이벤트에 참석했는지, 어떤 위치에서 체크인이 발생했는지, 누가 어떤 포스트에 코멘트 했는지 등을 나타낸다

### 속성 그래프

* 속성 그래프 모델에서 `정점`은 다음과 같은 요소로 구성된다
  * 고유한 식별자
  * 유출 (outgoing) 간선 집합
  * 유입 (incoming) 간선 집합
  * 속성 컬렉션 (key-value 쌍)
* 각 `간선`은 다음과 같은 요소로 구성된다
  * 고유한 식별자
  * 간선이 시작하는 정점 (`꼬리 정점` )
  * 간선이 끝나는 정점 (`머리 정점` )
  * 두 정점 간 관계 유형을 설명하는 레이블
  * 속성 컬렉션 (key-value 쌍)
* `관계형 스키마`를 사용해 `속성 그래프` 표현하기

  ```sql
  CREATE TABLE vertices (
    vertex_id integer PRIMARY KEY, 
    properties json
  );

  CREATE TABLE edges (
    edge_id integer PRIMARY KEY,
    tail_vertex integer REFERENCES vertices (vertex_id),
    head_vertex integer REFERENCES vertices (vertex_id), 
    label text,
    properties json
   );

  CREATE INDEX edges_tails ON edges (tail_vertex); 
  CREATE INDEX edges_heads ON edges (head_vertex);
  ```

  * `스키마 설명`
    * 두 개의 관계형 테이블 (하나는 정점, 하나는 간선)로 구성된 그래프 저장소
    * 각 정점, 간선 속성 저장을 위해 PostgreSQL `json` 데이터타입을 사용했다
    * 머리와 꼬리 정점은 각 간선마다 저장된다
    * 정점을 위한 `유입 간선` 과 `유출 간선` 의 집합이 필요하다면 edges 테이블에
      * `유입 간선` 은 `head_vertex` ,
      * `유출 간선` 은 `tail_vertex` 로 질의할 수 있다
  * `해당 모델의 중요한 면` 1. 정점은 다른 정점과 간선으로 연결된다 - 특정 유형과 관련 여부를 제한하는 스키마는 없다 2. 정점이 주어지면 정점의 유입과 유출 간선을 효율적으로 `찾을 수 있고`, 그래프를 `순회할 수 있다` - 즉, 일련의 정점을 따라 `앞 뒤 방향`으로 `순회`한다 3. 다른 유형의 관계에 서로 다른 레이블을 사용하면, - 단일 그래프에 다른 유형의 정보를 저장하면서도 - 데이터 모델을 깔끔하게 유지할 수 있다

### 사이퍼 질의 언어

* `사이퍼 (Cypher)` 는 속성 그래프를 위한 `선언형 질의 언어` 로, 네오포제이 그래프 데이터베이스 용으로 만들어졌다
* 보통 선언형 질의 언어는 질의를 작성할 때 수행에 대해 자세히 지정할 필요가 없다
  * `질의 최적화기`가 가장 효율적이라고 예측한 전략을 자동으로 선택하므로, 작성자는 나머지 애플리케이션만 작성하면 된다

### SQL의 그래프 질의

* 그래프 데이터를 관계형 구조로 넣어도 SQL을 사용해 질의할 수 있지만, 어려운 부분이 있다
  * 관계형 데이터베이스에서는 대개 질의에 필요한 조인을 미리 알고 있다
  * 그래프 질의에서는 찾고자 하는 정점을 찾기 전에 가변적인 여러 간선을 순회해야 한다
    * 즉, 미리 JOIN 수를 고정할 수 없다
* `SQL:1999` 이후로 가변 순회 경로에 대한 질의 개념은 `재귀 공통 테이블 식 (recursive common table expression)`을 사용해서 표현할 수 있다
  * 여기서 재귀 공통 테이블 식은 `WITH RECURSIVE 문`!
* 하지만 사이퍼와 비교하면 문법이 매우 어렵다
  * (예제 생략) 동일한 질의를 사이퍼 질의 언어는 4줄로 작성할 수 있는데 SQL은 29줄로 작성해야 한다
  * 이는 다양한 데이터 모델이 `서로 다른 사용 사례` 를 만족하기 위해 설계됐다는 사실을 보여준다
    * 애플리케이션에 적합한 데이터 모델을 선택하는 작업은 중요하다!

### 트리플 저장소와 스파클

* `트리플 저장소 모델` 은 속성 그래프 모델과 거의 동등하다
  * 이 모델은 같은 생각을 다른 용어를 사용해 설명한다
* 트리플 저장소에서는 모든 정보를 `주어(subject)`,, `서술어(predicate)` , `목적어(object)`처럼 간단한 세 부분(`three-part statements`) 형식으로 저장한다
* 트리플의 `주어`는 그래프의 `정점` 과 동등하다
* `목적어`는 두 가지 중 하나다
  1. 문자열이나 숫자 같은 `원시 데이터타입`의 값
     * 이 경우 트리플의 서술어와 목적어는 주어 정점에서 속성의 키, 값과 동등하다
     * ex)
       * (루시, 나이, 33)은 {”age”: 33} 속성을 가진 정점 lucy와 같다
  2. 그래프의 `다른 정점`
     * 이 경우 서술어는 그래프의 간선이고, 주어는 꼬리 정점이며, 목적어는 머리 정점이다
     * ex)
       * (루시, 결혼하다, 알랭) 에서 주어와 목적어인 루시와 알랭은 모두 정점이고, 서술어 결혼하다는 두 정점을 잇는 간선의 레이블이다
* `서술어`가 `간선`을 나타내면, `목적어`는 `정점`이 된다
  * ex) `서술어`가 `속성`이라면, `목적어`는 문자열 `리터럴`이 된다

### 시맨틱 웹

* 시맨틱 웹은 웹 사이트는 이미 사람이 읽을 수 있는 텍스트와 그림으로 정보를 제공하고 있으니, 컴퓨터가 읽게끔 기계가 판독 가능한 데이터로도 정보를 게시하는건 어떨까라는 개념이다
* `자원 기술 프레임워크 (Resource Description Framework: RDF)` 는 서로 다른 웹 사이트가 일관된 형식으로 데이터를 게시하기 위한 방법을 제안한다
  * RDF는 서로 다른 웹 사이트의 데이터가 일종의 전 인터넷 `“만물 데이터베이스(database of everything)”`인 `데이터 웹(web of data)` 에 자동으로 결합할 수 있게 한다

### 스파크 질의 언어

* `스파클(SPARQL)`은 RDF 데이터 모델을 사용한 트리플 저장소 질의 언어다
  * 스파클은 SPARQL Protocol and RDF Query Language의 줄임말이다
  * 스파클을 사이퍼보다 먼저 만들었 고 사이퍼의 패턴 매칭을 스파클에서 차용했기 때문에 이 둘은 매우 유사해 보인다
* 스파클은 훌륭한 질의 언어다
  * 시맨틱 웹이 아니더라도 애플리케이션이 내부적으로 사용하는 강력 한 도구가 될 수 있다

### 초석: 데이터로그

* 데이터로그(Datalog)는 스파클이나 사이퍼보다 훨씬 오래된 언어로 1980년대 학계에서 광범위하 게 연구됐다
  * 소프트웨어 엔지니어 사이에서는 잘 알려져 있지 않지만 그럼에도 중요 한 이유는 이후 질의 언어의 기반이 되는 초석을 제공하기 때문이다
  * 실제로 일부 데이터 시스템에서 데이터로그를 사용한다
    * ex) 데이토믹 - 데이터로그를 질의 언어로 사용
* 데이터로그의 데이터 모델은 트리플 저장소 모델과 유사하지만 조금 더 일반화됐다.
  * `(주어, 서술어, 목적어)`로 트리플을 작성하는 대신 `서술어(주어, 목적어)`로 작성한다

## 정리

* 역사적으로 데이터를 하나의 큰 트리 (계층 모델) 로 표현하려고 노력했지만, 다대다 관계로 표현하기에는 `트리 구조`가 적절하지 않았다
  * 이 문제를 해결하기 위해 `관계형 모델`이 고안됐다
* 새롭게 등장한 비관계형 데이터저장소인 `NoSQL`은 다음과 같은 두 가지 주요 갈래가 있다
  1. 문서 데이터베이스는 데이터가 문서 자체에 포함돼 있으면서 하나의 문서와 다른 문서 간 관계가 거의 없는 사용 사례를 대상으로 한다.
  2. 그래프 데이터베이스는 문서 데이터베이스와는 정반대로 모든 것이 잠재적으로 관련 있다는 사용 사례를 대상으로 한다
* 세 가지 모델(문서, 관계형, 그래프) 모두 현재 널리 사용하고 있으며, 각 모델은 `각자의 영역에서 훌륭`하다
  * 한 모델을 다른 모델로 흉내 낼 수 있지만(예를 들어 그래프 데이터는 관계형 데이터베이스 로 표현할 수 있다) 그 결과는 대부분 엉망이다
  * 이것이 바로 단일 만능 솔루션이 아닌 각기 `목적에 맞는 다양한 시스템`을 보유해야 하는 이유다
* 문서 및 그래프 데이터베이스가 가진 공통점 중 하나는 일반적으로 저장할 데이터를 위한 스키마를 강제하지 않아 변화하는 요구사항에 맞춰 애플리케이션을 쉽게 변경할 수 있다는 점이다
  * 하지만 애 플리케이션은 데이터가 특정 구조를 갖는다고 가정할 가능성이 높다
  * 이는 스키마가 `명시적`인지(`쓰기`에 강요됨) `암시적`인지(`읽기`에 다뤄짐)의 문제일 뿐이다
* 각 데이터 모델은 `고유한 질의 언어`나 `프레임워크`를 제공한다
  * 몇 가지 예로 SQL, 맵리듀스, 몽고 DB의 집계 파이프라인, 사이퍼, 스파클, 데이터로그 등을 설명했다
