대표적인 NoSQL 데이터베이스이다.
NoSQL :
NoSQL은 (non SQL 또는 non relational) 기존 RDBMs 형태의 관계형 데이터베이스가 아닌 다른 형태의 데이터 저장 기술을 의미하며, 관계형 데이터 베이스의 한계를 극복하기 위한 데이터 저장소의 새로운 형태로, 수평적 확장성을 갖고 있다.
RDBMS가 클라이언트/서버 환경에 맞는 데이터 저장기술이라면, NoSQL은 클라우드 환경에 맞는 저장 기술이다.
NoSQL의 특징
- NoSQL은 RDBMS와는 달리 데이터 간의 관계를 정의하지 않는다.
- 가장 큰 특징 중 하나는 관계형 데이터 베이스인 RDBMS가 데이터의 관계를 Foreign Key 등으로 정의하고 이를 이용해 Join 등의 관계형 연산을 한다고 하면, NoSQL은 데이터 간의 관계를 정의하지 않는다. 데이터 테이블은 그냥 하나의 테이블이며 각 테이블 간의 관계를 정의하지 않고 일반적으로 테이블 간의 Join도 불가능하다.
- RDBMS에 비해 훨씬 더 대용량의 데이터를 저장할 수 있다.
- RDBMS의 복잡도와 용량의 한계를 극복하기 위한 목적으로 등장한 만큼 페타바이트급의 대용량 데이터를 저장할 수 있다.
- 분산형 구조이다.
- NoSQL은 기존 RDBMS와는 다르게 하나의 고성능 머신에 데이터를 저장하는 것이 아니라 일반적인 서버 수십 대를 연결해 데이터를 저장 및 처리하는 구조를 갖는다. 즉 분산형 구조를 통해 데이터를 여러 대의 서버에 분산해 저장하고 분산 시에 데이터를 상호 복제해 특정 서버에 장애가 발생했을 때에도 데이터 유실이나 서비스 중지가 없는 구조의 형태를 가진다.
- 고정되지 않은 테이블 스키마를 갖는다.
- RDBMS와는 다르게 테이블의 스키마가 유동적이다. 데이터를 저장하는 컬럼은 각기 다른 이름과 다른 데이터 타입을 갖는 것이 허용된다.
- 스키마란? 데이터베이스의 구조와 제약 조건에 관한 전반적인 명세를 기술한 메타데이터의 집합이다.
RDBMS 와 NoSQL의 차이
- RDBMS
장점
- - DATA를 Column과 Row 형태로 저장
- - 데이터의 분류, 정렬, 탐색 속도가 비교적 빠름
- - SQL 이라는 구조화 된 질의를 통해 데이터를 다룰 수 있음
- - 작업의 완전성을 보장
- 단점
- - 데이터의 UPDATE가 빠르다
- - 반드시 스키마 규격에 맞춰서 데이터를 다뤄야 한다.
- - 데이터 처리에 대한 부하 발생시, 처리가 어렵다.
- NoSQL
장점
- - 데이터간의 관계를 정의 하지 않는다(테이블 간의 관계(JOIN) 불필요)
- - RDBMS 보다 복합도가 떨어져, 훨씬 대용량의 데이터를 저장, 관리 할 수 있다.
- - 테이블에 스키마가 정해져있지 않아 데이터 저장이 비교적 자유롭다.
- - 수평적 확장이 어려운 RDBMS보다는 수평적 확장이 쉽다.
단점
- - 스키마가 정해져 있지 않아, 데이터에 대한 규격화가 되어있지 않음.
- - DATA를 UPDATE하는데 비교적 느림
- - 중복된 데이터가 저장될 수 있다.
NoSQL에 대한 오해
NoSQL이 등장하면서 기존의 RDBMS의 단점들이 부각되기는 하지만 여전히 RDMB의 성능과 기능은 뛰어나다.
설정과 튜닝을 통해서 NoSQL에 비해 원하는 성능과 확장성을 충분히 갖추고 있다.
NoSQL을 검토할때는 3가지 측면을 고려한다.
데이터의 규모와 데이터의 처리속도 그리고 데이터의 형태이다.
많은 데이터와 빠른 속도로 데이터를 처리하는 것을 다 만족하는 데이터베이스는 없습니다.
인메모리 기반의 데이터베이스는 당연히 속도가 빠르겠지만 확장성에 있어서 한계가 있기 때문에 수십테라바이트, 수백테라바이트의 빅데이터를 다루기에는 적합하지 않습니다.
반면, 빅데이터를 처리하는 경우에는 상대적으로 읽기/쓰기/업데이트등의 성능 및 기능의 제약이 존재합니다.
데이터의 복잡도에 따라서 성능의 차이가 발생하게 됩니다. 단순한 작은 크기의 값을 다루는 key/value 인 경우에는 그 성능이 매우 뛰어난 데이터베이스더라도 처리하는
value의 데이터 크기가 좀 커지고 복잡해지면 성능이 떨어지는 경우도 있지만 NoSQL의 경우에는 좀 더 복잡한 데이터 구조를 수용하면서도 성능을 어느정도 보장해주는것이 있다.
NoSQL들을 보면 메모리를 많이 사용해서 성능도 향상시키면서 확장성도 어느 정도갖추도록 아키텍쳐들이 개선되어 가고 있지만 이를 위해서 필요한 서버의 성능도 올라가야합니다.
이를 위해 서버의 비용도 부담이 되기 때문에 이점도 고려를 해야하는 사항입니다.
샤딩
- 샤딩이란
빅데이터를 저장하기 위해서는 한 대의 서버에 저장하는 것은 불가능합니다. 초당 엄청난 양의 데이터를 insert 하면 Write scaling 문제가 발생하여 서비스 성능 저하를 유발합니다. 따라서 이를 해결하기 위해 여러 대의 서버에 분산 처리하는 것이 이상적입니다.
샤딩을 하게 되면 여러 대의 독립된 프로세스가 병렬로 작업을 동시에 수행하여 이상적으로 빠른 처리 성능을 보장받습니다. 또 하나의 서버에서 관리를 하면 유실 시 큰 손실이 따르게 됩니다. 분산 처리를 하면 이러한 위험 요소로부터 안전하게 데이터를 저장, 관리할 수 있습니다.
- 샤딩의 목적
- 데이터의 분산 저장 (한대의 서버에 빅 데이터를 저장하는것이 힘들다)
- 데이터를 분산하여 순차적으로 저장한다면, 부하를 분산할 수 있다.
- 백업과 복구 전략
- 시스템 성능 향상, 데이터 유실 가능성으로부터 보호
- 미리 분산하여 안정적이고 효과적인 시스템을 운영한다.
- 여러 독립된 프로세스로 병렬 작업을 하기 때문에 빠른 처리 성능을 보인다.
- shard key 구성
shard key 구성 방법은 mongoDB 샤딩 시스템 구축할 때 가장 중요합니다. 이는 여러 개의 샤드 서버로 분할될 기준 필드를 가리키며, partition과 load balancing에 기준이 됩니다. 따라서 적절한 카디널리티를 가진 필드가 shard key로 선택되어야 합니다.
카디널리티는 조건을 만족하는 데이터의 분산 정도를 나타내는 값으로 전체 데이터 중에서 조건을 만족하는 데이터의 분포가 넓으면 낮은 카디널리티라고 하며 분포가 좁으면 높은 카디널리티라고 표현합니다. 예를 들어 사원번호는 고유한 값이니 높은 카디널리티입니다. 남/여 라는 필드로 샤드키를 구성하면 낮은 카디널리티입니다.
결과적으로 카디널리티가 너무 높거나 낮은 필드는 shard key로는 적절하지 않습니다. 왜냐면 데이터를 적절하게 분산 저장하기에는 데이터 값의 유형이 적절하게 잘 분포되어야 할 필요가 있습니다.
- replication
복제는 여러 서버에서 데이터베이스 서버를 분산하고 관리하는 것입니다. "장애는 항상 발생한다"라고 하는 피할 수 없는 사실 때문에 대부분의 데이터베이스 관리 시스템에서 복제는 핵심적 요소입니다. mongoDB에서 복제는 아래와 같은 특징을 가집니다.
- Master/slave 관계를 갖는 원본과 복사본 사이입니다.
- Master에서 쓰기 operation을 수행하고 이러한 operation을 Master의 oplog(명령어 기록)에 기록합니다. slave는 Master의 oplog를 복제하고 각자의 데이터 세트에 오퍼레이션을 비동기 방식으로 동일하게 적용됩니다.
- Master는 (read/write)용이고, slave는 master의 데이터를 미러링하고 있는 read 전용입니다. Slave에 write가 가능하도록 설정해 줄 수 있지만 속도면에서 권장하지 않습니다.
- 리플리카셋 구성
- 마스터 서버(1개) : 메인 데이터베이스 서버, 사용자가 접속하는 대상 서버
- 슬레이브 서버(n개): 서브 형태의 서버, 마스터 서버와의 데이터를 동기화하는 서버
- 아비터 서버(1개): 감시용 서버, 문제가 생긴 서버를 대신해서 동작할 다른 서버를 지정하는 등의 역할을 하는 서버
몽고DB (MongoDB):
MongoDB는 문서 데이터베이스로, JSON과 유사한 문서에 데이터를 저장합니다. 이것이 데이터에 대해 생각하는 가장 자연스러운 방법이며 기존의 행 / 열 모델보다 훨씬 더 표현력 있고 강력합니다.
· MongoDB 는 유연하고 JSON과 유사한 문서에 데이터를 저장합니다 . 즉, 필드는 문서마다 다를 수 있으며 시간에 따라 데이터 구조를 변경할 수 있습니다.
· 문서 모델 은 응용 프로그램 코드의 객체에 매핑 되므로 데이터를 쉽게 사용할 수 있습니다.
· 임시 쿼리, 인덱싱 및 실시간 집계 는 데이터에 액세스하고 분석하는 강력한 방법을 제공합니다
· MongoDB는 기본적 으로 분산 데이터베이스 이므로 고 가용성, 수평 확장 및 지리적 분포가 내장되어 있고 사용하기 쉽습니다.
· MongoDB는 무료로 사용할 수 있습니다 .
설치
https://www.mongodb.com/try/download/community
Document Oriented Database
· Document는 RDBMS의 record와 비슷한 개념, 데이터구조는 한개이상의 key - value pair 으로 이뤄져 있다.
여기서 _id, username, name은 key이고 그 오른쪽에 있는 값들은 value이다.
_id 는 12bytes의 hexadecimal 값으로서, 각 document의 유일함을 제공한다.
이 값은 첫 4bytes는 현재 timestamp, 다음 3bytes는 machine id, 다음 2bytes 는 MongoDB 서버의 프로세스 id, 마지막 3byte는 추가될때마다 값이 높아지는 순차번호이다.
MongoDB와 RDBMS의 차이점
RDBMS | MongoDB |
데이터베이스(Database) | 데이터베이스(Database) |
테이블 | 컬렉션 |
레코드 | 도큐먼트 |
컬럼 | 필드 |
인덱스 | 인덱스 |
쿼리의 결과로 '레코드(Record)반환 | 쿼리의 결과로 '커서(Cursor)' 반환 |
"커서 (Cursor)"
MongoDB가 쿼리의 결과를 반환해주는 결과로써 클라이언트 - 사이드에서는 다양한 처리가 가능하다.
DB가 넘겨주는 결과수를 제한할 수 있으며, 결과의 개수를 건너뛸 수 있으며, key 조합을 통해 결과를 분류하거나 검색 방향을 제어할 수 있는 등의 강력한 오퍼레이션을 구성할 수 있다.
Database 생성 : use
use DATABASE_NAME 명령어를 통해 Database를 생성 할 수 있다.
use newDatabase 명령어를 사용하면 newDatabase라는 이름을 가진 database를 새롭게 생성합니다.
(이때 만약 해당 이름을 가진 데이터베이스가 존재한다면 새롭게 만들어지지 않고 기존에 있던 데이터베이스를 사용하게 됩니다.)
> use mongodb_tutorial
switched to db mongodb_tutorial
현재 사용중인 데이터베이스를 확인하려면 db명령어를 입력
> db
mongodb_tutorial
내가 만든 데이터베이스 리스트들을 확인하려면 show dbs 명령어를 입력
> show dbs
local 0.000GB
리스트에서 만든 데이터베이스를 보려면 최소 한개의 Document를 추가해야한다.
> db.book.insert({"name": "MongoDB Tutorial", "author": "nam"});
WriteResult({ "nInserted" : 1 })
> show dbs
local 0.000GB
mongodb_tutorial 0.000GB
Database 제거 : db.dropDatabase()
Database를 제거할땐 db.dropDatabase() 명령어를 사용
이 명령어를 사용하기 전, use DATABASE_NAME으로 삭제하고자 하는 데이터베이스를 선택해줘야한다.
ex : mongodb_tutorial 데이터베이스 제거
> use mongodb_tutorial
switched to db mongodb_tutorial
> db.dropDatabase();
{ "dropped" : "mongodb_tutorial", "ok" : 1 }
Collection 생성: db.createCollection()
Collection을 생성할 때는 db.createCollection(name, [options]) 명령어를 사용한다.
name은 생성하려는 컬렉션의 이름이며 option은 document 타입으로 구성된 컬렉션의 설정값이다.
Option:
필드 | 타입 | 설명 |
capped | Boolean | 이값을 true로 설정하면 capped collection을 활성화 시킵니다. Capped collection이란, 고정된 크기를 가진 컬렉션으로서, size가 초과되면 가장 오래된 데이터를 덮어씁니다. 이값을 true로 설정하면 size값을 꼭 설정해야 한다. |
autoIndex | Boolean | 이 값을 true로 설정하면, _id 필드에 index를 자동으로 생성한다. 기본값은 false |
size | number | Cappeed collection을 위해 해당 컬렉션의 최대 사이즈를 ~byte로 지정한다. |
max | number | 해당 컬렉션에 추가 할 수 있는 최대 갯수를 설정한다. |
생성 예제 1 : test 데이터베이스에 books 컬렉션을 옵션없이 생성
> use test
swited to db test
> db.createCollection("book")
{ "ok" : 1 }
생성 예제2: test데이터베이스에 articles 컬렉션을 옵션과 함께 생성
> db.createCollection("articles", {
... capped: true,
... autoIndex: true,
... size: 6142800,
... max: 10000
... })
{ "ok" : 1 }
생성 예제3: 따로 createCollection() 메소드를 사용하지 않아도 document를 추가하면 자동으로 컬렉션이 생성된다.
> db.people.insert({"name": "nam"})
WriteResult({ "nInserted" : 1 })
내가 만든 Collection 리스트들을 확인하려면 show collections 명령어를 입력한다.
> show collections
articles
books
people
Collection 제거: db.COLLECTION_NAME.drop()
Collection을 제거 할 땐 drop() 메소드를 사용한다.
이 명령어를 제거하기 전, 사용 할 데이터베이스를 우선 설정해야 한다.
예제 : test 데이터베이스의 people 컬렉션을 제거한다.
> use test
switched to db test
> show collections
articles
books
people
mongodb_tutorial
> db.people.drop()
true
> show collections
articles
books
mongodb_tutorial
Document 추가: db.COLLECTION_NAME.insert(document)
insert() 메소드를 사용하여 Document를 추가 할 수 있다.
이 명령어를 사용하기 전 데이터를 추가 할 데이터베이스를 선택해야한다.
배열형시의 인자를 전달해주면 여러 다큐먼트를 동시에 추가 할 수 있다.
예제1: 한개의 다큐먼트를 books 컬렉션에 추가한다.
> db.books.insert({"name": "NodeJS Guide", "author": "nam"})
예제2: 두개의 다큐먼트를 books 컬렉션에 추가한다.
> db.books.insert([
... {"name": "Book1", "author": "name"},
... {"name": "Book2", "author": "gyu"}
... ]);
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
Document 조회 : db.COLLECTION_NAME.find(query, projection)
query | Optional(선택적), 다큐먼트를 조회할때 기준을 정합니다. 기준이 없이 컬렉션에 있는 모든 다큐먼트를 조회할 때는 이 매개변수를 비우거나 비어있는 다큐먼트 {}를 전달하세요 |
projection | Option. 다큐먼트를 조회할 때 보여질 field를 정합니다. |
반환(return) 값 : cursor
criteria에 해당하는 Document들을 선택하여 cursor를 반환합니다. cursor는 query 요청의 결과값을 가르키는 pointer 입니다. cursor 객체를 통하여 보이는 데이터의 수를 제한 할 수 있고, 데이터를 sort 할 수 도 있습니다.
예제1 모든 다큐먼트 조회
> db.articles.find()
{ "_id" : ObjectId("56c0ab6c639be5292edab0c4"), "title" : "article01", "content" : "content01", "writer" : "Velopert", "li
{ "_id" : ObjectId("56c0ab6c639be5292edab0c5"), "title" : "article02", "content" : "content02", "writer" : "Alpha", "likes
{ "_id" : ObjectId("56c0ab6c639be5292edab0c6"), "title" : "article03", "content" : "content03", "writer" : "Bravo", "likes ] }
예제2 다큐먼트를 줄바꿈으로 조회
> db.articles.find().pretty()
{
"_id" : ObjectId("56c0ab6c639be5292edab0c4"),
"title" : "article01",
"content" : "content01",
"writer" : "Velopert",
"likes" : 0,
"comments" : [ ]
}
{
"_id" : ObjectId("56c0ab6c639be5292edab0c5"),
"title" : "article02",
"content" : "content02",
"writer" : "Alpha",
"likes" : 23,
"comments" : [
{
"name" : "Bravo",
"message" : "Hey Man!"
}
]
}
{
"_id" : ObjectId("56c0ab6c639be5292edab0c6"),
"title" : "article03",
"content" : "content03",
"writer" : "Bravo",
"likes" : 40,
"comments" : [
{
"name" : "Charlie",
"message" : "Hey Man!"
},
{
"name" : "Delta",
"message" : "Hey Man!"
}
]
}
예제3 writer 값이 "Nam"인 Document를 조회
> db.articles.find({"writer": "Nam"}).pretty()
{
"_id" : ObjectId("56c0ab6c639be5292edab0c4"),
"title" : "article01",
"content" : "content01",
"writer" : "Nam",
"likes" : 0,
"comments" : [ ]
}
예제4 likes 값이 30 이하인 Document 조회
> db.articles.find({"likes": {$lte: 30}}).pretty()
{
"_id" : ObjectId("56c0ab6c639be5292edab0c4"),
"title" : "article01",
"content" : "content01",
"writer" : "Nam",
"likes" : 0,
"comments" : [ ]
}
{
"_id" : ObjectId("56c0ab6c639be5292edab0c5"),
"title" : "article02",
"content" : "content02",
"writer" : "Alpha",
"likes" : 23,
"comments" : [
{
"name" : "Bravo",
"message" : "Hey Man!"
}
]
}
Query 연산자
$eq (equals) | 주어진 값과 일치하는 값 |
$gt (greater than) | 주어진 값보다 큰 값 |
$gte (gtrater than or equals) | 주어진 값보다 크거나 같은 값 |
$lt (less than) | 주어진 값보다 작은 값 |
$lte (less than or equals) | 주어진 값보다 작거나 같은 값 |
$ne (not equal) | 주어진 값과 일치하지 않는 값 |
$in | 주어진 배열 안에 속하는 값 |
$nin | 주어진 배열 안에 속하지 않는 값 |
$or | 논리 연산자 or |
$and | 논리 연산자 and |
예제5 like 값이 10보다 크고 30보다 작은 Document 조회
> db.articles.find( { "likes": { $gt: 10, $lt: 30 } } ).pretty()
{
"_id" : ObjectId("56c0ab6c639be5292edab0c5"),
"title" : "article02",
"content" : "content02",
"writer" : "Alpha",
"likes" : 23,
"comments" : [
{
"name" : "Bravo",
"message" : "Hey Man!"
}
]
}
예제6 writer 값이 배열 ["Alpha", "Bravo"] 안에 속한 값인 Document 조회
> db.articles.find( { “writer”: { $in: [ “Alpha”, “Bravo” ] } } ).pretty()
{
"_id" : ObjectId("56c0ab6c639be5292edab0c4"),
"title" : "article01",
"content" : "content01",
"writer" : "Bravo",
"likes" : 0,
"comments" : [ ]
}
{
"_id" : ObjectId("56c0ab6c639be5292edab0c5"),
"title" : "article02",
"content" : "content02",
"writer" : "Alpha",
"likes" : 23,
"comments" : [
{
"name" : "Bravo",
"message" : "Hey Man!"
}
]
}
Document 수정 : db.COLLECTION_NAME.update()
Collection을 수정할 때에는 db.COLLECTION_NAME.update() 명령어를 수행한다.
- db.collection.updateOne(filter, update, options)
예제1 특정 field 업데이트하기
// { name: "Jhon", age: 29} 에서 age를 25로 변경
> db.user.updateOne(
{ name: "Jhon"},
{ $set: {age: 25}}
)
특정 field의 값을 수정할 땐 $set 연산자를 사용합니다.
예제2 document를 replace 하기
// Betty document를 새로운 document로 대체한다.
> db.people.update( { name: "Betty" }, { "name": "Betty 2nd", age: 1 })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
예제3 특정 field를 제거하기
// David document의 score field를 제거한다.
> db.people.update( { name: "David" }, { $unset: { score: 1 } } )
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
scroe : 1의 1은 true를 의미합니다.
예제4 criteria에 해당되는 document가 존재하지 않는다면 새로 추가하기
// upsert 옵션을 설정하여 Elly document가 존재하지 않으면 새로 추가
> db.people.update( { name: "Elly" }, { name: "Elly", age: 17 }, { upsert: true } )
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("56c893ffc694e4e7c8594240")
})
예제5 여러 document의 특정 field 수정하기
// age가 20 보다 낮거나 같은 document의 score를 10으로 설정
> db.people.update(
... { age: { $lte: 20 } },
... { $set: { score: 10 } },
... { multi: true }
... )
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 0 })
예제6 배열 filed에 값 추가하기 (skills: [])
> db.user.updateOne(
{name: "Jhon"},
{$push: {skills: 'react'}}
)
> db.user.find()
{ "_id" : ObjectId("601b95c5c3ade512b9dbaed7"), "name" : "Jhon", "age" : 25, "skills" : [ "react" ] }
예제7 배열 field에 값 추가하기 + 정렬
# 여러개 추가 시 $each 사용
# 알파벳순으로 정렬 시 $sort 사용
> db.user.updateOne(
{name: "Jhon"},
{$push:
{skills:
{
$each:['vue', 'react'],
$sort:1
}
}
}
)
> db.find()
{ "_id" : ObjectId("601b95c5c3ade512b9dbaed7"), "name" : "Jhon", "age" : 25, "skills" : [ "angular", "react", "vue" ] }
{ "_id" : ObjectId("601b9695c3ade512b9dbaf14"), "name" : "name", "age" : 25 }
$sort 값을 내림차순으로 정렬하려면 -1
예제8 배열 field에 값 제거하기
> db.user.updateOne(
... {name:"Jhon"},
... {$pull: {skills:'react'}}
... )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.user.find()
{ "_id" : ObjectId("601b95c5c3ade512b9dbaed7"), "name" : "Jhon", "age" : 25, "skills" : [ "angular", "vue" ] }
{ "_id" : ObjectId("601b9695c3ade512b9dbaf14"), "name" : "name", "age" : 25 }
Document 제거: db.COLLECTION_NAME.remove(criteria, justOne)
remove(criteria, justOne) 메소드를 사용하여 Document를 제거 할 수 있다.
parameter | type | 설명 |
criteria | document | 삭제 할 데이터의 기준 값 (criteria) 이다. 이 값이 {}이면 컬렉션의 모든 데이터를 제거한다. |
justOne | boolean | 선택적(Optional) 매개변수이며 이 값이 true 면 1개의 다큐먼트만 제거한다. 이 매개변수가 생략되면 기본 값은 false로서, criteria에 해당되는 모든 다큐먼트를 제거한다. |
예제1 전체 데이터를 사제하고자 할때
> db.books.remove({ })
예제2 books 컬렉션에서 "name"이 "Book1"인 타큐먼트를 제거
> db.books.find({"name": "Book1"})
{ "_id" : ObjectId("601b4ba429863d6b029dab0f"), "name" : "Book1", "author" : "name" }
> db.books.remove({"name": "Book1"})
WriteResult({ "nRemoved" : 1 })
> db.books.find()
{ "_id" : ObjectId("601b4ae729863d6b029dab0e"), "name" : "NodeJS Guide", "author" : "nam" }
{ "_id" : ObjectId("601b4ba429863d6b029dab10"), "name" : "Book2", "author" : "gyu" }
명령어
db.currentOp()
- DB의 현재 동작 상태를 나타냄
{
"type" : "op",
"host" : "DESKTOP-SQRU1UC:27017",
"desc" : "conn45",
"connectionId" : 45,
"client" : "127.0.0.1:61838",
"appName" : "MongoDB Shell",
"clientMetadata" : {
"application" : {
"name" : "MongoDB Shell"
},
"driver" : {
"name" : "MongoDB Internal Client",
"version" : "4.4.3"
},
"os" : {
"type" : "Windows",
"name" : "Microsoft Windows 10",
"architecture" : "x86_64",
"version" : "10.0 (build 18363)"
}
},
"active" : true,
"currentOpTime" : "2021-02-08T12:11:25.148+09:00",
"opid" : 7330683,
"lsid" : {
"id" : UUID("25ebdc03-6e34-458e-be79-baabb56d2060"),
"uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")
},
"secs_running" : NumberLong(0),
"microsecs_running" : NumberLong(149),
"op" : "command",
"ns" : "admin.$cmd.aggregate",
"command" : {
"currentOp" : 1,
"lsid" : {
"id" : UUID("25ebdc03-6e34-458e-be79-baabb56d2060")
},
"$db" : "admin"
},
"numYields" : 0,
"locks" : {
},
"waitingForLock" : false,
"lockStats" : {
"timeLockedMicros" : {
"r": NubmerLong(424242),
"w": NubmerLong(0),
},
"timeAcquiringMricros": {
"r":NubmerLong(1592),
"w": NubmerLong(0)
},
"waitingForFlowControl" : false,
"flowControlStats" : {
}
},
- opid - operation의 unique id. db.killOp(Opid) 로 kill 시킬수 있다. Operation이 yield, finds, remove 상태일때는 kill 시킬 수 있다. 그러나 lock때문에 holding 상태이거나, waiting 상태라면 kill 시킬 수 없다.
- active - operation이 running중일때, 이 값이 false 이면, operation 이 다른작업에 밀렸거나, lock때문에 waiting 상태임을 뜻한다.
- secs_running - operation 이 걸린시간
- op - operation의 type. 대개 query, insert, update or remove 가 된다.
- desc - /var/log/mongod.log 에서 검색시 사용 (ex: conn424)
- locks - lock의 type. “^”은 global lock을 가리킨다. (v2.6 에서는 보이지 않음)
- waitingForLock - 이 operation이 현재 blocking 상태인지, 아니면 lock을 하기 위해 waiting 하고 있는지 나타낸다.
- numYields - operation 이 yield된 횟수.
- lockstats.timeAcquiringMicros - operatioin이 lock을 하기 위해 기다린 시간.
MongoDB 도구파일들
MongoDB 4.4 버전 미만의 버전들에서는 아래와 같은 데이터베이스 도구들이 존재함 (4.4버전부터는 MongoDB서버와 별도로 출시)
각 파일들은 mongoDB의 유틸리티 파일들로 현재 실행중인 mongodb 인스턴스의 상태를 파악할 수 있다
1.mongodump - 현재 데이터베이스 정보를 내보내고 저장 (백업)
>mongodump -h dbhost -d dbname -o dbdirectory
백업할 DB명과 복제할 디렉터리 PATH를 지정해주면 백업할 수 있다.
2.mongorestore- 저장된 정보를 다시 불러와 읽는 명령어 (백업한내용 복구)
>mongorestore -h dbhost -d dbname --directoryperdb dbdirectory
3.mongofiles - Gridfs 개체의 MongoDB 인스턴스에 저장된 파일을 조작할 수 있다.
mongofiles <options> <connection-string> <command> <filename or _id>
4.mongoimport, mongoexport - 서버에 데이터를 백업해서 다른 환경의 서버에 사용하고 싶을 때 사용
mongoimport <options> <connection-string> <file>
mongoexport --collection=<coll> <options> <connection-string>
5.mongostat - 1초에 한번씩 mongod, mongos 성능을 측정한다
mongostat <options> <connection-string> <polling interval in seconds>
6.mongotop - read/write/total i/o 정보를 보여준다.
특정 콜렉션의 성능이 떨어지는것도 확인할 수 있다.
db.stats() : 디스크 사용량 확인
db - 데이터베이스의 이름
collections - 해당 데이터베이스의 컬렉션 수
views - 해당 데이터베이스의 view 수
objects - 모든 컬렉션에서 데이터베이스의 개체(documents) 수
avgObjSize - 각 문서 (document)의 평균 크기 (바이트) 이다. dataSize를 문서수로 나눈것이다.
dataSize - 이 데이터베이스에 보관된 압축되지 않은 데이터의 총 크기이다.
storageSize - 문서 저장을 위해 데이터베이스의 컬렉션에 할당 된 총 공간.
indexes - 데이터베이스의 모든 컬렉션에 대한 총 인덱스 수를 포함한다.
indexSize - 데이터베이스에 생성 된 모든 인덱스의 총 크기
fsTotalSize - MongoDB가 데이터를 저장하는 파일 시스템에 있는 모든디스크 용량의 총 크기
보충내용
1. PATH 설정과 같은 부분들 내용 보강
환경변수 설정하기
mongodb가 설치되어있는 폴더의 주소를 복사합니다.
설치위치는 C>Program Files > MongoDB > Server > 4.4 > bin 입니다.
C:\Program Files\MongoDB\Server\4.4\bin 경로를 복사해서 환경 변수 설정 페이지로 들어갑니다.
시스템 변수에서 Path를 찾아 편집을 클릭후 새로만들기를 눌러 복사했던 경로를 붙여넣고 확인을 눌러 설정합니다.
MongoDB 설치 과정에서 MongoDB Compass 를 설치하였다면 Compass를 실행하면 아래와 같은 화면이 보일 것입니다. File in connection fields individually 버튼을 클릭하여 설치한 MongoDB와 연결합니다.
기본적으로 Hostname이 localhost, port가 27017로 되어있습니다. connect 버튼을 클릭해 연결을 해줍니다. 연결이 되었다면 기본적으로 MongoDB에 들어가 있는 admin, config, local Connections이 확인이 된다면 정상적으로 연결된 것입니다.
Collection을 생성할 수 있고 document를 입력하여 넣을 수도 있다.
ObjectId -> _id(기본 인덱스키) -> MongoDB와 같은 분산 database에서는 key를 서버에서 만들지 않고 클라이언트에서 만들기 때문에
유일하게 만드는 방법이 있나? -> 자동으로 만들어주는데, 수동으로 만들어야되는 상황이 있을 때 클라이언트에서 유일하게 만드는 방법이 있나요?
우선 ObjectId가 무엇인지에 대해서 알아 볼 필요가 있다.
ObjectId란 무엇인가
ObjectId는 같은 document 내에서 유일함이 보장되는 12 byte binary data이다.
전통적인 centrailzed 되어 있는 시스템이라면 한 collection 내에서 유일함을 보장하는 것을 쉽게 할 수 있다. 하지만 sharding을 하는 MongoDB에서 유일함을 보장하는 것은 기존과는 다른것이 필요하다. 그리고 이 방법의 모든것이 ObjectId이다.
전통적인 RDBMS에서 Primary key를 만들 때는 DB 서버로 data를 보내서 중복되지 않는 key를 골라서 그 값을 key로 저장하는 방식을 이용한다.
하지만 MongdoDB와 같은 분산 database에서는 key를 서버에서 만들지 않고 클라이언트에서 만든다.
MongoDB는 자신이 필요한 shard에게만 query를 요청한다. 다시 말해서 client에 해당하는 mongos가 config server의 data를 토대로 어떤 shard가 어느 범위의 값을 가졌는지를 저장하고 있다가 query를 요청할 때 자신이 필요로 하는 shard에게만 요청한다.
따라서 shard key에 해당하는 data가 미완성인 상태로 서버에 저장하도록 요청할 수 없고, client가 ObjectId를 생성하여 값을 저장하도록 요청한다.
use 명령어의 경우에는 생성된 걸 사용하는 건가요? 아니면 그냥 진짜 생성하는건가요?
use newDatabase 명령어를 사용하면 newDatabase라는 이름을 가진 database를 새롭게 생성합니다.
(이때 만약 해당 이름을 가진 데이터베이스가 존재한다면 새롭게 만들어지지 않고 기존에 있던 데이터베이스를 사용하게 됩니다.)
현재 샤드 상태 조회
mongos> printShardingStatus()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("602a2a47e184548308abe092")
}
shards:
{ "_id" : "shard0000", "host" : "localhost:10001" }
{ "_id" : "shard0001", "host" : "localhost:10002" }
{ "_id" : "shard0002", "host" : "localhost:10003" }
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
2 : Success
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "stoneIs", "partitioned" : true, "primary" : "shard0000" }
stoneIs.stone
shard key: { "_id" : 1 }
chunks:
shard0000 1
shard0001 1
shard0002 1
{ "_id" : { "$minKey" : 1 } } -->> { "_id" : ObjectId("602a2b933d90ad335c448ed5") } on : shard0001 Timestamp(2, 0)
{ "_id" : ObjectId("602a2b933d90ad335c448ed5") } -->> { "_id" : ObjectId("602a2b933d90ad335c448ee9") } on : shard0002 Timestamp(3, 0)
{ "_id" : ObjectId("602a2b933d90ad335c448ee9") } -->> { "_id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(3, 1)
'NoSQL > MongoDB' 카테고리의 다른 글
MongoDB 인덱스 확인 (TTL 설정 확인) (0) | 2024.01.19 |
---|---|
MongoDB 샤딩 (샤딩과 복제 차이, 수평파티셔닝이란, 샤딩의 종류) (0) | 2023.04.26 |
MongoDB Sharding(샤딩) (0) | 2021.03.17 |