NoSQL

개발 공부 기록·2021년 8월 6일
0

DB

목록 보기
3/3
post-thumbnail

NoSQL

데이터의 구조가 고정되어 있지 않은 데이터베이스를 NoSQL
=> 테이블을 사용하지 않고 데이터를 다른 형태로 저장

NoSQL에서는 데이터를 읽어올 때 스키마에 따라 데이터를 읽어 옴(schema on read)

데이터를 입력하는 방식에 따라, 데이터를 읽어올 때 영향을 미침

ex) 대표적인 NoSQL은 몽고DB, Casandra

NoSQL 기반의 비관계형 데이터베이스 구성

  • Key-Value 타입 : 속성을 Key-Value의 쌍으로 나타내는 데이터를 배열의 형태로 저장
    Key는 속성 이름을 뜻하고, Value는 속성에 연결된 데이터 값을 의미
    ex) Redis, Dynamo
  • 문서형(Document) 데이터베이스 : 데이터를 테이블이 아닌 문서처럼 저장하는 데이터베이스를 의미
    JSON과 유사한 형식의 데이터를 문서화하여 저장
    각각의 문서는 하나의 속성에 대한 데이터를 가지고 있고, 컬렉션이라고 하는 그룹으로 묶어서 관리
    ex) MongoDB
  • Wide-Column 데이터베이스 : 데이터베이스의 열(column)에 대한 데이터를 집중적으로 관리하는 데이터베이스
    각 열에는 key-value 형식으로 데이터가 저장되고, 컬럼 패밀리(column families)라고 하는 열의 집합체 단위로 데이터를 처리
    데이터 처리에 필요한 열을 유연하게 선택할 수 있다는 점에서 규모가 큰 데이터 분석에 주로 사용되는 데이터베이스 형식
    ex) Cassandra, HBase
  • 그래프(Graph) 데이터베이스 : 자료구조의 그래프와 비슷한 형식으로 데이터 간의 관계를 구성하는 데이터베이스
    노드(nodes)에 속성별(entities)로 데이터를 저장 / 각 노드간 관계는 선(edge)으로 표현
    ex) Neo4J, InfiniteGraph

특징

1. 데이터 저장(Storage)

NoSQL은 key-value, document, wide-column, graph 등의 방식으로 데이터를 저장

2. 스키마(Schema)

NoSQL은 관계형 데이터베이스보다 동적으로 스키마의 형태를 관리
=> 행을 추가할 때 즉시 새로운 열을 추가할 수 있고, 개별 속성에 대해서 모든 열에 대한 데이터를 반드시 입력하지 않아도 됨

3. 쿼리(Querying)

비관계형 데이터베이스의 쿼리는 데이터 그룹 자체를 조회하는 것에 초점
=> 구조화 되지 않은 쿼리 언어로도 데이터 요청이 가능 UnQL(UnStructured Query Language)

4. 확장성(Scalability)

NoSQL로 구성된 데이터베이스는 수평적으로 확장
=> 보다 값싼 서버 증설, 또는 클라우드 서비스 이용하는 확장

NoSQL 데이터베이스를 위한 서버를 추가적으로 구축하면, 많은 트래픽을 보다 편리하게 처리 가능

NoSQL 사용하는 경우

1. 비구조적인 대용량의 데이터를 저장하는 경우

자유로운 형태로 데이터를 저장할 수 있으므로 필요에 따라서 새로운 데이터 유형을 추가 가능
정형화되지 않은 많은 양의 데이터가 필요한 경우, NoSQL이 효율적

2. 클라우드 컴퓨팅 및 저장공간을 최대한 활용하는 경우

데이터베이스를 클라우드 기반으로 쉽게 분리 할 수 있도록 지원하여, 저장 공간을 효율적으로 사용

수평적 확장의 형태로 증설하므로, 이론상 무한대로 서버를 계속 분산시켜 DB를 증설 가능

3. 빠르게 서비스를 구축하고 데이터 구조를 자주 업데이트 하는 경우

스키마를 미리 준비할 필요가 없어서, 개발을 빠르게 해야하는 경우에 매우 적합

MongoDB

MongoDB는 대표적인 NoSQL 도큐먼트 데이터베이스
도큐먼트 데이터베이스는 데이터를 테이블이 아닌, 문서처럼 저장하는 데이터베이스
일반적으로 도큐먼트 데이터베이스에서는 JSON 유사 형식으로 데이터를 문서화
각각의 도큐먼트는 데이터를 필드-값 의 형태로 가지고 있고, 컬렉션이라고 하는 그룹으로 묶어서 관리
NoSQL 데이터베이스에서는 데이터를 행과 열이 아닌, 체계적인 방식으로 저장
ex) 도서카드 목록함

속성

도큐먼트는 객체와 같이 데이터를 필드-값 쌍(Field - Value pair)으로 저장하고 구성
도큐먼트에서 필드는 데이터의 고유한 식별자이고, 값은 주어진 식별자와 관련된 데이터
도큐먼트의 모음을 컬렉션
데이터베이스는 여러개의 컬렉션으로 구성됨

  • 도큐먼트(Document)
    필드 - 값 쌍으로 저장된 데이터
  • 필드(Field)
    데이터 포인트를 위한 고유한 식별자
  • 값(Value)
    주어진 식별자와 연결된 데이터
  • 컬렉션(Collection)
    MongoDB의 도큐먼트로 구성된 저장소
    일반적으로 도큐먼트 간의 공통 필드가 있음
    데이터베이스 마다 많은 컬렉션이 있고, 컬렉션마다 많은 도큐먼트가 있을 수 있음

Atlas Cloud

MongoDB에서는 아틀라스(Atlas)로 클라우드에 데이터베이스를 설정
아틀라스는 GUI와 CLI로 데이터를 시각화, 분석, 내보내기, 그리고 빌드하는 데에 사용
아틀라스 사용자는 클러스터를 배포 할 수 있으며, 클러스터는 그룹화된 서버에 데이터를 저장

레플리카 세트

레플리카 세트동일한 데이터를 저장하는 몇 개의 연결된 MongoDB 인스턴스의 모음

도큐먼트나 컬렉션을 변경할 경우, 변경된 데이터의 중복 사본이 레플리카 세트에 저장됨

레플리카 세트의 인스턴스 중 하나에 문제가 발생하더라도 데이터는 그대로 유지되며, 레플리카 세트의 애플리케이션에서 나머지 작업가능
=> 동일한 데이터를 저장하는 소수의 연결된 머신, 레플리카 세트 중 하나에 문제가 발생하더라도, 데이터를 그대로 유지가능

클러스터(서버 그룹)를 배포하면, 자동으로 레플리카 세트가 구성됨

인스턴스

로컬 또는 클라우드에서 특정 소프트웨어를 실행하는 단일 머신, MongoDB에서는 클라우드에서 실행되는 데이터베이스

클러스터

데이터를 저장하는 서버 그룹으로 여러 대의 컴퓨터를 네트워크를 통해 연결하여 하나의 단일 컴퓨터처럼 동작하도록 제작한 컴퓨터

JSON vs. BSON

shell을 이용하여 도큐먼트를 조회하거나 업데이트 할 때, 도큐먼트는 JSON(JavaScript Object Notation) 형식으로 출력

JSON 형식으로 도큐먼트를 작성하기 위한 조건

  • {} 중괄호로 도큐먼트가 시작하고, 끝나야 함
  • 필드와 값이 콜론(:)으로 분리되어야 하며, 필드와 값을 포함하는 쌍은 쉼표(,)로 구분됨
  • 문자열인 필드도 쌍따옴표("")로 감싸야 함

JSON텍스트 형식이기 때문에 읽기 쉽지만, 파싱이 느리고 메모리 사용이 비효율적
JSON은 기본 데이터 타입만을 지원하기 때문에, 사용 할 수 있는 데이터 타입에 제약
=> 이런 문제점을 해결하기 위한 방안으로 BSON(Binary JSON) 형식을 도입

BSON컴퓨터의 언어에 가까운 이진법에 기반을 둔 표현법
JSON보다 메모리 사용이 효율적이며 빠르고, 가볍고, 유연하고 더 많은 데이터 타입을 사용 가능

MongoDB는 JSON형식으로 작성된 것은 무엇이든 데이터베이스에 추가할 수 있고, 쉽게 조회 가능
내부에서는 속도, 효율성, 유연성의 장점이 있는 BSON으로 데이터를 저장, 사용

MongoDB의 데이터는 BSON의 형태로 저장이 되고, 보통 읽기 쉬운 JSON의 형태로 출력

  • JSON 형식으로 데이터를 가져오고 내보내기 위한 명령어인 mongoimportmongoexport
  • BSON 형식으로 가져오고 내보내기 위한 명령어 mongorestoremongodump

CRUD 문법

Insert(C)

모든 MongoDB 도큐먼트는 모든 도큐먼트가 _id 필드를 기본값으로 반드시 가지고 있어야 한다
도큐먼트 내 필드와 값이 똑같다 할지라도, _id 값이 다르면 서로 다른 도큐먼트로 간주

새로운 도큐먼트를 추가할 때, _id 값에 임의적으로 고유한 값을 생성해서 사용할 수도 있지만 보통은 ObjectId 타입(12byte, 24char)의 값으로 사용
또한 도큐먼트를 추가할 때, _id 필드와 값을 특정하지 않았다면, 자동적으로 _id 필드가 생성되고 값에 ObjectId 타입이 할당됨

db.컬렉션이름.insert()
insert() 명령어를 사용하면 주어진 도큐먼트 배열의 인덱스 순서대로 작업이 실행된다.
ordered를 추가하면 순서에 상관없이 고유한 _id를 가진 도큐먼트는 모두 컬렉션에 삽입된다.
사용자가 존재하지 않는 컬렉션에 도큐먼트를 넣는 경우, 그와 동시에 컬렉션이 만들어지게 된다.

Find(R)

  • db.컬렉션이름.find()
  • db.컬렉션이름.find().pretty() : 읽기 편하게 조회됨
  • db.컬렉션이름.find().count() : 데이터 수
  • db.컬렉션이름.findOne(): 하나의 데이터 조회

Update(U)

  • db.컬렉션이름.updateOne() : 주어진 기준에 맞는 다수의 도큐먼트가 있다면, 그 중 작업에 맞는 첫번째 도큐먼트 하나만 업데이트
  • db.컬렉션이름.updateMany() : 쿼리문과 일치하는 모든 도큐먼트를 업데이트
    연산자
  • $inc : 특정 필드 값을 주어진 만큼 증가
  • $set : 특정 필드 값을 주어진 값으로 바꿔줌
  • $push : 배열로 이루어진 필드의 값에 요소를 추가하기 위한 연산자

Delete(D)

  • db.컬렉션이름.deleteOne(): 주어진 기준에 맞는 다수의 도큐먼트 중, 첫번째 도큐먼트 하나를 삭제
  • db.컬렉션이름.deleteMany(): 쿼리문과 일치하는 모든 도큐먼트를 삭제
  • db.컬렉션이름.drop(): 컬렉션 삭제

연산자와 프로젝션

1. 비교 연산자

  • $eq (Equal to)
  • $ne (Not Equal to)
  • $gt (Greater Than)
  • $gte (Greater Than or Equal to)
  • $lt (Less Than)
  • $lte (Less Than or Equal to)

문법: { field : { operator : value } }

쿼리 연산자는 데이터베이스 내에서 데이터를 찾는 다양한 방법을 제공
비교 연산자를 사용하면 특정 범위 내에서 데이터를 찾을 수 있다.
비교 연산자를 지정하지 않으면 $eq가 기본 연산자로 사용

2. 논리 연산자

  • $and: 지정된 모든 쿼리 절을 충족하는 도큐먼트를 반환
    연산자가 지정되지 않았을 때 기본 연산자로 사용됨
    동일한 연산자를 두 번 이상 포함해야 할 때는 $and를 명시
  • $or: 쿼리 절 중 하나라도 일치하는 도큐먼트가 있다면 해당 도큐먼트를 반환
    $nor: 모든 절과 일치하지 않는 도큐먼트를 반환
    { : [{statement1}, {statement2}, ...]}
  • $not: $nor의 단일 버전같이 뒤의 조건을 만족하지 않는 모든 도큐먼트를 반환
    {$not: {statemnet}}

논리 연산자를 사용하면 데이터 검색을 보다 세분화 가능

3. 표현 연산자

  • $expr: 표현력이 풍부하여 하나 이상의 작업을 수행 가능
    쿼리 내에서 집계 표현식(Aggregation Expression)을 사용할 수 있으며 { $expr : { expression } } 구문을 사용
    $expr를 이용해 변수와 조건문을 사용 가능
    $expr를 이용해 같은 도큐먼트 내의 필드들을 서로 비교 가능

$를 사용하여 각각의 도큐먼트마다 달라지는 특정 필드의 값을 변수처럼 비교 가능(필드의 값을 참조할 때)

집계 표현식에서 비교 연산자 => {<operator>: {<field>, <value>}}

4. 배열 연산자

  • $push: 배열에 요소를 추가하거나 이전에 다른 유형의 값이었던 경우 해당 필드를 배열 타입의 필드로 바꿀 수 있다.
    지정된 배열 필드의 배열 순서와 관계없이 지정된 모든 요소가 포함된 모든 도큐먼트들이 있는 커서를 반환
  • $all: 배열 필드에 지정한 요소가 있는 모든 도큐먼트를 반환 /배열 요소의 순서와 상관없이 지정된 요소가 포함된 모든 도큐먼트를 찾을 수 있다.
  • $size: 특정한 요소를 찾지않는다면, $size만을 사용하여 배열 길이로만 쿼리 가능
    지정된 배열 필드가 주어진 길이와 정확히 일치하는 모든 도큐먼트들이 있는 커서를 반환

배열 연산자를 쓰지않고 배열 필드를 쿼리하는 경우 배열을 지정한다면 해당 배열과 정확히 일치하는 배열을 가진 도큐먼트를 찾는다.
문자열로 요소를 지정한다면 해당 요소가 배열에 포함된 모든 도큐먼트를 찾는다.

5. 배열 연산자와 Projection

  • $elemMatch(projection): 지정한 배열 필드가 도큐먼트에 존재하고 조건에 맞는 요소가 있는 경우에만 해당 필드를 결과에 포함시킴
  • $elemMatch(query)

6. 배열과 서브 도큐먼트를 쿼리

값으로 도큐먼트가 있는 필드가 있고 해당 필드의 값으로 또 도큐먼트가 있는 경우에도 점 표기법을 사용하여 해당 계층에서 도큐먼트 자체가 아닌 필드의 값을 가져올 수 있다.

특정 요소 위치로 배열 필드를 쿼리하거나 서브 도큐먼트의 요소를 쿼리하기 위해 MQL은 점 표기법을 사용하여 도큐먼트에서 이러한 요소의 주소를 지정한다.

점 표기법을 사용하여 원하는 만큼 중첩된 도큐먼트로 이동가능
배열에 점 표기법을 사용하려면 배열에서 요소의 위치를 지정해야한다.

$regex: 정규식 연산자인$regex를 사용하여 일치시키려는 문자열을 지정 가능

7. Aggregation Framework

Aggregation Framework는 MongoDB에서 데이터를 쿼리하는 가장 간단한 방법 중 하나

MongoDB 쿼리 언어를 사용하는 모든 작업은 Aggregation Framework를 사용하여 수행 가능

Aggregation Framework에서는 find가 아닌 aggregate 명령을 사용
aggregate를 사용하면 도큐먼트를 필터링 하지않고 그룹으로 데이터를 집계하거나 데이터를 수정 가능
aggregate를 사용하면 데이터 찾기 및 프로젝션 없이 작업을 수행하거나 계산 가능
aggregate를 사용할땐 대괄호를 이용해 배열을 인자로 사용, 이는 파이프라인처럼 배열 요소의 순서대로 작업을 하기 때문

Aggregation Framework에 $match 등과 같은 필터링 단계가 없으면 데이터 요약, 계산 및 그룹화를 수행 할 때 원본 데이터를 수정하지 않는다는 점을 유의

Aggregation Framework는 데이터를 계산, 재구성 및 재정립하는 기능을 통해 MQL의 필터링 기능을 능가하는 강력한 도구

  • $match: 필터링
  • $project: Projection
  • $group: 들어온 데이터 스트림을 여러개로 그룹화하는 연산자
    $group 단계는 이전 단계에서 도큐먼트를 받을 때 _id 필드에 표현식을 사용하여 이 도큐먼트가 속한 그룹을 식별
    $group 구문의 두 번째 부분을 사용하면 파이프 라인을 통해 들어오는 데이터에 대해 더 많은 양적 분석을 수행 가능

$group$sum을 이용하여 그룹화된 데이터를 리듀스하는 방법

Index

MongoDB_index - memorization

다중 인덱스(compound index)를 만들면, 모든 도큐먼트를 조회할 필요가 없다. 어떤 필드에 대한 인덱스를 만드는 것은 해당 필드의 값을 기준으로 도큐먼트의 위치 정보를 담은 데이터를 생성하는 것이다.

createIndex

인덱스를 생성하기 위해서는 createIndex()라는 메소드를 사용
db.collection_name.createIndex({<필드명>:1, <필드명>: -1})
createIndex의 파라미터로 인덱스를 적용할 필드를 전달
이에 따른 값을 1로 지정하면 오름차순으로, -1로 하면 내림차순으로 정렬
이때 필드명을 1개를 지정하면 단일 필드 인덱스, 필드명이 2개 이상이면 다중 인덱스(compound index)

인덱스에는 이 외에도 createIndex() 메소드의 두번째 파라미터로 속성을 추가 가능
db.collection_name.createIndex({<필드명>:1}, {<속성 property>:true})

  • Unique(유일함 속성) : _id 필드와 같이 컬렉션에 단 한 개의 값만 존재할 수 있는 속성
    db.members.createIndex( { "user_id": 1 }, { unique: true } )
  • Partial(부분적 속성) : 도큐먼트의 조건을 정해 일부 도큐먼트에만 인덱스를 적용
    partialFilterExpression 옵션을 사용
    db.restauratns.createIndex({"cuisine":1, "name":1}, {partialFilterExpression:{ rating: {$gt:4}}})
  • TTL(Time-To-Live) : 이 속성은 Date 타입 혹은 Date배열 타입의 필드에 적용가능
    이 속성을 사용하면 특정시간이 지난 후, 도큐먼트를 컬렉션에서 삭제
    db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )

getIndexes, dropIndex

  • 생성된 인덱스를 조회할 떄는 getIndexes 메소드를 사용
    db.collection_name.getIndexes()
  • 생성된 인덱스를 삭제할 때는 dropIndex 메소드를 사용
    db.collection_name.dropIndex(name)
    or
    db.collection_name.dropIndex({<field>:1})
    모든 인덱스를 삭제하고 싶을 때에는 다음과 같이 복수형의 메소드를 사용
    db.collection_name.dropIndexes()

MongoDB 공식 문서 참조

profile
둔필승총(鈍筆勝聰) - 기억보다는 기록을

0개의 댓글