programing

mongodb "schema" 생산 변화 처리 방법

lovejava 2023. 6. 28. 21:14

mongodb "schema" 생산 변화 처리 방법

mongodb + node.js + mongoose.js ORM 백엔드를 사용합니다.

_id 필드가 없는 개체의 중첩 배열이 있다고 가정합니다.

mongoose.Schema({
  nested: [{
    _id: false, prop: 'string'
  }]
})

그런 다음 _id 필드를 모든 중첩된 객체 d에 추가하여 몽구스 스키마가

mongoose.Schema({
  nested: [{
    prop: 'string'
  }]
})

그럼 제가 프로덕션 DB를 수정하기 위해 스크립트를 실행해야 하는 거죠?이러한 변화를 처리하는 가장 좋은 방법은 무엇입니까?변경사항을 구현하기 위해 어떤 툴(또는 접근 방식)을 사용하는 것이 가장 좋습니까?

스키마가 없는 데이터베이스의 중요한 이점 중 하나는 새 스키마 레이아웃으로 전체 데이터베이스를 업데이트할 필요가 없다는 것입니다.DB에 있는 문서 중 일부에 특정 정보가 없는 경우 코드가 대신 적절한 작업을 수행하거나 해당 레코드로 작업을 수행하도록 선택할 수 있습니다.

또 다른 선택사항은 문서를 다시 볼 때만 필요에 따라 게으르게 업데이트하는 것입니다.이 경우 레코드별/문서 버전 플래그를 선택할 수 있습니다. 이 플래그는 처음에는 나타나지 않을 수도 있습니다(따라서 '버전 0'을 나타냅니다).하지만 그것조차도 선택 사항입니다.대신 데이터베이스 액세스 코드는 필요한 데이터를 찾고, 코드 업데이트 후 추가된 새로운 정보이기 때문에 존재하지 않는 경우 최대한 결과를 입력합니다.

를 들어, 를들어, 환변 _id:false 표으로로MongoId 때 후에 쓸 때), 필드, 또가읽때 (힐는업후다때쓰질여시고에트그리이데코드또,▁field그리), 고▁the,▁the_id:false가 현재 설정되어 있습니다. 그런 다음 반드시 필요한 경우에만 변경하고 기록합니다.

컬렉션을 검토하고 각 문서에 새 필드를 추가할 스크립트를 작성해야 합니다.정확한 방법은 DB의 크기와 스토리지 시스템의 성능에 따라 달라집니다.문서에 필드를 추가하면 크기가 변경되어 대부분의 경우 재배치됩니다.이 작업은 IO에 영향을 미치며 IO에 의해 제한됩니다.컬렉션이 몇 천 개의 문서에 불과하거나 최대 10만 개에 불과할 경우 전체 컬렉션이 메모리에 저장되고 이후에 모든 IO가 발생하기 때문에 한 번의 루프에서 반복할 수 있습니다.그러나 수집이 사용 가능한 메모리를 훨씬 초과하는 경우 접근 방식이 더 복잡해집니다.우리는 보통 MongoDB의 프로덕션 사용에서 다음 단계를 따릅니다.

  • 시간 초과로 커서 열기=False
  • 문서 덩어리를 메모리로 읽기
  • 이 문서에 대한 업데이트 쿼리 실행
  • IO 하위 시스템의 과부하 및 운영 애플리케이션의 손상을 방지하기 위해 잠시 동안 절전 모드로 전환
  • 완료될 때까지 반복
  • 커서를 닫습니다 :)

문서 청크의 크기와 절전 기간을 실험적으로 결정해야 합니다.일반적으로 마이그레이션 기간 동안 mongostats에서 QR/QW를 사용하지 않습니다.느린 드라이브(Amazon의 EBS와 같은)의 대규모 수집의 경우, 이 IO 안전 접근 방식은 몇 시간에서 며칠까지 걸릴 수 있습니다.

@Michael Korbakov 대답을 확장하면서, 나는 그의 단계를 실행했습니다.mongo셸 스크립트(MongoDB 참조 매뉴얼 참조 정보)mongo셸 스크립트).

중요: MongoDB 참조 매뉴얼에 명시된 대로 스크립트 실행mongo셸은 각 배치 가져오기 및 대량 실행에 대한 연결 지연 시간을 줄이기 때문에 성능에 도움이 될 수 있습니다.

고려해야 할 단점은mongo셸 명령은 항상 동기화되지만 대량 실행은 이미 각 청크에 대한 병렬 처리를 수행하므로 이 사용 사례에 적합합니다.

코드:

// constants
var sourceDbName = 'sourceDb';
var sourceCollectionName = 'sourceColl';
var destDbName = 'destdb';
var destCollectionName = 'destColl';
var bulkWriteChunckSize = 1000;
// for fetching, I figured 1000 for current bulkWrite, and +1000 ready for next bulkWrite
var batchSize = 2000;    
var sourceDb = db.getSiblingDB(sourceDbName);
var destDb = db.getSiblingDB(destDbName);

var start = new Date();

var cursor = sourceDb[sourceCollectionName].find({}).noCursorTimeout().batchSize(batchSize);

var currChunkSize = 0;
var bulk = destDb[destCollectionName].initializeUnorderedBulkOp();
cursor.forEach(function(doc) {
    currChunkSize++;
    bulk.insert({
        ...doc,
        newProperty: 'hello!',
    }); // can be changed for your need, if you want update instead

    if (currChunkSize === bulkWriteChunckSize) {
        bulk.execute();

        // each bulk.execute took for me 130ms, so i figured to wait the same time as well
        sleep(130);

        currChunkSize = 0;
        bulk = destDb[destCollectionName].initializeUnorderedBulkOp();
    }
});

if (currChunkSize > 0) {
    bulk.execute();
    currChunkSize = 0;
}

var end = new Date();
print(end - start);

cursor.close();

언급URL : https://stackoverflow.com/questions/14290568/how-to-handle-mongodb-schema-change-in-production