07. 업데이트, 원자적 연산, 삭제

주요 내용
  • 도큐먼트 업데이트
  • 도큐먼트 원자적 프로세싱

도큐먼트 업데이트#

전체 대치#

db.users.update({_id: user_id}, doc)
  • 도큐먼트 전체가 doc으로 대치되므로 주의

특정 필드 수정#

db.users.update(
{_id: user_id},
{$set: {email: 'mongodb-user@mongodb.com'}}
)

전체 대치 vs 특정 필드 수정#

  • 리뷰수 증가 예제
doc = db.products.findOne({_id: product_id})
// 전체 대치
doc['total_reviews'] += 1
db.products.update({_id: doc._id}, doc)
// 특정 필드 수정
db.products.update(
{_id: product_id}
{$inc: {total_reviews: 1}})
  • 대치는 일반적이고, 쉽다
  • 특정 필드 수정은 좀 더 나은 성능을 가짐
    • 도큐먼트를 원자적으로 업데이트하는 데 적합
    • optimistic locking 을 제공
      • 레코드를 잠그지 않고 업데이트 연산이 제대로 수행되는 것을 보장하기 위한 기술

도큐먼트 원자적 프로세싱#

  • 원자적 업데이트는 다른 연산이 끼어들 수 없는 업데이트
  • MongoDB의 모든 업데이트는 원자적 업데이트
  • findAndModify: 도큐먼트를 업데이트한 후 업데이트 된 도큐먼트를 반환
    • 다른 수정 연산 전에 조회로 결과를 받아옴
    • job queue와 state machine 을 만들 수 있음 (transaction 같이 구현 가능)
newDoc = db.orders.findAndModify({
'query': {
user_id: user_id,
state: 'CART',
},
'update': {
$set: {
state: 'PRE_AUTHORIZE'
}
},
'new': true // true 이면 업데이트 된 도큐먼트 반환, 기본적으로 false
})

동시성, 원자성, 고립#

  • 3.0 WiredTigher 엔진에서는 컬렉션 레벨에서 하나의 쓰기 여러개 읽기를 제공
    • 도큐먼트 수준의 잠금을 제공
  • 잠금기능이 제공해주는 최적화
    • 램에 있는 doc의 내부맵을 DB가 유지 (doc이 램에 없으면 페이징 될때까지 다른 연산 수행)
    • 쓰기 잠금 양보 (잠시 잠금을 해제했다가 다른 읽기 쓰기에 양보)
  • 잠금기능을 무효화하기 위해 $isolated 옵션 사용 가능
    • 해당 연산 실패 시 암시적 롤백이 발생하지 않음
    • 샤드된 컬렉션에서 동작하지 않음

업데이트 성능#

MMAPv1 에 적용되는 이야기

  • $inc 와 같은 연산은 대상 필드의 타입이 지정된 사이즈 (int, double 등) 이기 때문에 bson 크기 변하지않아 성능에 좋음
  • $push 는 주의해서 사용하며, 업데이트는 doc을 최대한 작게 유지
  • padding factor
    • doc 사이즈가 늘어날 것을 대비해 디스크 사이즈를 확보하는 지수
    • 지정된 패딩 사이즈를 넘어갈 경우 패딩 팩터를 곱해 storage size를 확보함
Last updated on