programing

MongoDB: 문서 크기가 쿼리 성능에 영향을 미칩니까?

starjava 2023. 7. 6. 21:43
반응형

MongoDB: 문서 크기가 쿼리 성능에 영향을 미칩니까?

MongoDB 이 포함된 MongoDB 에 의해 백업되는 모바일 .User수백만 건의 문서를 수집했습니다.

이제 사용자와 연결되어야 하는 수십 가지 속성을 가정해 보겠습니다. 예를 들면,_id의 값Friend 이름, 문서, 사이, 사진, 열배의 _id의 값Game문서, 최종 날짜, 게임 내 통화 수 등.

수백만 개의 사용자 문서에 대규모로 증가하는 배열을 생성하고 업데이트하면 각 사용자 문서에 '무게'가 추가되거나 전체 시스템에 속도가 느려질지 걱정입니다.

문서당 16MB는 절대로 인식되지 않을 것입니다. 그러나 이러한 증가하는 목록을 직접 저장하면 문서가 10-20배 더 커질 것이라고 안심할 수 있습니다.

질문: 이것이 MongoDB의 문제입니까?문서 크기가 투영 및 인덱스 등을 사용하여 쿼리를 적절하게 관리하는지 여부도 중요합니까?들어 외부 대 문서 ? 예를 들어 외부 목록 대 임베딩 목록_id직접적인 가치관?

다른 말로 하면: 만약 내가 사용자의 것을 원한다면.last_loginvalue,를 합니다.last_login필드가 조금이라도 다를 경우User문서가 100kb 대 5mb입니까?

을 사용자를 : 특사용모두찾으면려를자정▁or면찾려으▁with▁i▁users모▁alast_login문서 크기가 그런 종류의 쿼리에 영향을 미칩니까?

질문을 다시 표현하는 한 가지 방법은 문서가 각각 16MB인 경우 100만 개의 문서 쿼리가 더 오래 걸리는지 여부입니다.

제 경험으로 볼 때 문서 크기가 작을수록 쿼리 속도가 빨라집니다.

저는 25,000개의 문서와 비교하여 50,000개의 문서에 대한 쿼리를 수행했는데 25,000개의 쿼리가 몇 밀리초에서 1-3초까지 눈에 띄게 빨랐습니다.생산 시 시차는 약 2배에서 10배 더 많습니다.

문서 크기가 적용되는 한 가지 측면은 질의 정렬입니다. 이 경우 문서 크기는 질의 자체의 실행 여부에 영향을 미칩니다.저는 2,000개 정도의 문서를 정렬하려고 여러 번 이 한계에 도달했습니다.

일부 솔루션에 대한 추가 참조: https://docs.mongodb.org/manual/reference/limits/ #operations https://docs.mongodb.org/manual/reference/operator/aggregation/sort/ #syslog-memory-limit

결국 최종 사용자가 어려움을 겪게 됩니다.

허용할 수 없을 정도로 느린 성능을 유발하는 큰 쿼리를 해결하려고 할 때저는 보통 데이터의 하위 집합을 사용하여 새 컬렉션을 만들고 정렬 및 제한과 함께 많은 쿼리 조건을 사용합니다.

이것이 도움이 되길 바랍니다!

우선 MongoDB가 패딩 팩터와 2가지 크기의 할당을 참조하여 문서를 저장하는 방법에 대해 읽어보는 데 약간의 시간을 할애해야 합니다.

http://docs.mongodb.org/manual/core/storage/ http://docs.mongodb.org/manual/reference/command/collStats/ #collStats.padding 계수

간단히 말해, MongoDB는 원래 문서를 저장할 때 확장을 위해 추가 공간을 할당하려고 합니다.2size 할당의 힘은 버전 2.6에서 기본 접근 방식이 되었으며, 여기서 문서 크기는 2의 거듭제곱으로 증가합니다.

전체적으로 모든 업데이트가 원래 크기 할당에 포함되면 성능이 훨씬 향상됩니다.그렇지 않은 경우 전체 문서를 충분한 공간이 있는 다른 곳으로 이동해야 하므로 더 많은 읽기 및 쓰기 작업이 발생하고 스토리지가 사실상 단편화되기 때문입니다.

시간이 지남에 따라 문서 크기가 10배에서 20배로 증가할 경우, 삽입, 업데이트 및 읽기 빈도에 따라 문서당 여러 번 이동할 수 있습니다.이 경우 고려할 수 있는 몇 가지 접근 방식이 있습니다.

초기 삽입 시 일반 문서 수명 증가의 대부분(예: 90%)을 포함할 수 있는 충분한 공간을 할당합니다.이는 처음에는 공간 사용에서 비효율적이지만, 성능 저하 없이 문서가 증가함에 따라 시간이 지남에 따라 효율성이 증가합니다.실제로 스토리지 비용을 미리 지불하고 나중에 사용하여 시간이 지남에 따라 성능을 향상시킬 수 있습니다.

"오버플로우" 문서 작성 - 일반적인 80-20 규칙이 적용되고 문서의 80%가 특정 크기에 적합하다고 가정합니다.이 양을 할당하고 예를 들어 친구가 100명 이상이거나 게임 문서가 100개 이상인 경우 문서가 나타낼 수 있는 오버플로 컬렉션을 추가합니다.오버플로 필드는 이 새 컬렉션의 문서를 가리키며 응용프로그램은 오버플로 필드가 있는 경우에만 새 컬렉션을 찾습니다.80%의 사용자가 정상적으로 문서를 처리할 수 있으며, 필요하지 않은 80%의 사용자 문서에 많은 스토리지를 낭비하지 않고 추가적인 애플리케이션 복잡성을 감수할 수 있습니다.

두 경우 모두 적절한 인덱스를 작성하여 적용되는 쿼리를 사용하는 것을 고려합니다.

적용된 쿼리는 다음과 같은 쿼리입니다.

all the fields in the query are part of an index, and
all the fields returned in the results are in the same index.

인덱스가 쿼리를 "적용"하기 때문에 MongoDB는 쿼리 조건을 일치시키고 인덱스만 사용하여 결과를 반환할 수 있습니다. MongoDB는 쿼리를 수행하기 위해 문서를 볼 필요가 없습니다.

색인만 쿼리하는 것이 색인 외부의 문서를 쿼리하는 것보다 훨씬 빠를 수 있습니다.인덱스 키는 일반적으로 카탈로그를 만드는 문서보다 작으며, 인덱스는 일반적으로 RAM으로 사용할 수 있거나 디스크에 순차적으로 위치합니다.

이 접근 방식에 대한 자세한 내용은 http://docs.mongodb.org/manual/tutorial/create-indexes-to-support-queries/ 을 참조하십시오.

MongoDB에서 큰 문서를 다룰 때의 경험을 공유하고 싶습니다...하지 마!

사용자가 base64로 인코딩된 파일(일반적으로 이미지 및 스크린샷)을 문서에 포함하도록 허용하는 실수를 범했습니다.우리는 결국 각각 2Mb에서 10Mb에 이르는 ~500,000개의 문서를 수집하게 되었습니다.

이 컬렉션에서 단순 집계를 수행하면 클러스터가 중단됩니다!

MongoDB에서는 특히 이와 같은 큰 문서의 경우 집계 쿼리가 매우 많을 수 있습니다.Aggregate의 인덱스는 일부 조건에서만 사용할 수 있으며, 이는 다음과 같이 사용할 수 있습니다.$group인덱스가 사용되고 있지 않으므로 MongoDB는 모든 문서를 스캔해야 합니다.

더 작은 크기의 문서가 있는 컬렉션에서 동일한 쿼리를 실행하는 속도가 매우 빨랐고 리소스 사용량도 그리 많지 않았습니다.

따라서 큰 문서를 사용하여 MongoDB에서 쿼리하면 성능, 특히 Aggregate에 큰 영향을 미칠 수 있습니다.

또한 문서가 만들어진 후에도 계속 증가할 것이라는 것을 알고 있다면(예: 지정된 엔티티(문서)에 로그 이벤트 포함) 이러한 하위 항목에 대한 컬렉션을 만드는 것이 좋습니다. 크기가 나중에 문제가 될 수도 있기 때문입니다.

브루노.

간단한 대답: 네.

긴 답변: 쿼리에 영향을 미치는 방식은 쿼리의 특성, 사용 가능한 메모리 및 인덱스 크기와 같은 많은 요인에 따라 달라집니다.

당신이 할 수 있는 최선은 테스트하는 것입니다.

아래 코드는 smallDocuments와 bigDocuments라는 이름의 두 컬렉션을 생성하며, 각각 1024개의 문서는 큰 문자열을 포함하는 필드 'c'와 _id만 다릅니다.빅 문서 컬렉션에는 약 2GB가 있으므로 실행에 주의하십시오.

const numberOfDocuments = 1024;

// 2MB string x 1024 ~ 2GB collection
const bigString = 'a'.repeat(2 * 1024 * 1024);

// generate and insert documents in two collections: shortDocuments and
// largeDocuments;
for (let i = 0; i < numberOfDocuments; i++) {
  let doc = {};
  // field a: integer between 0 and 10, equal in both collections;
  doc.a = ~~(Math.random() * 10);

  // field b: single character between a to j, equal in both collections;
  doc.b = String.fromCharCode(97 + ~~(Math.random() * 10));

  //insert in smallDocuments collection
  db.smallDocuments.insert(doc);

  // field c: big string, present only in bigDocuments collection;
  doc.c = bigString;

  //insert in bigDocuments collection
  db.bigDocuments.insert(doc);
}

이 코드를 파일(예: create-test-data.js)에 넣고 다음 명령을 입력하여 몽고셸에서 직접 실행할 수 있습니다.

mongo testDb < create-test-data.js

시간이 좀 걸릴 겁니다.그런 다음 다음과 같은 몇 가지 테스트 쿼리를 실행할 수 있습니다.

const numbersToQuery = [];

// generate 100 random numbers to query documents using field 'a':
for (let i = 0; i < 100; i++) {
  numbersToQuery.push(~~(Math.random() * 10));
}

const smallStart = Date.now();
numbersToQuery.forEach(number => {
  // query using inequality conditions: slower than equality
  const docs = db.smallDocuments
    .find({ a: { $ne: number } }, { a: 1, b: 1 })
    .toArray();
});
print('Small:' + (Date.now() - smallStart) + ' ms');

const bigStart = Date.now();
numbersToQuery.forEach(number => {
  // repeat the same queries in the bigDocuments collection; note that the big field 'c'
  // is ommited in the projection
  const docs = db.bigDocuments
    .find({ a: { $ne: number } }, { a: 1, b: 1 })
    .toArray();
});
print('Big: ' + (Date.now() - bigStart) + ' ms');

다음과 같은 결과를 얻었습니다.

색인 없음:

Small: 1976 ms
Big: 19835 ms

모두 후, 두를컬모필드 'a'싱후로,.createIndex({ a: 1 }):

Small: 2258 ms
Big: 4761 ms

이것은 큰 문서에 대한 쿼리가 더 느리다는 것을 보여줍니다.인덱스를 사용하면 큰 문서의 결과 시간이 작은 문서의 결과 시간보다 100% 이상 큽니다.

제 제안은 다음과 같습니다.

  1. 쿼리에 동일 조건 사용(https://docs.mongodb.com/manual/core/query-optimization/index.html#query-selectivity);
  2. 적용된 쿼리 사용(https://docs.mongodb.com/manual/core/query-optimization/index.html#covered-query);
  3. 메모리에 맞는 인덱스 사용(https://docs.mongodb.com/manual/tutorial/ensure-indexes-fit-ram/);
  4. 문서를 작게 유지합니다.
  5. 텍스트 인덱스를 사용하여 구문 쿼리가 필요한 경우 전체 컬렉션이 메모리에 맞는지 확인합니다(https://docs.mongodb.com/manual/core/index-text/ #storage-intervancements-and-performance-interval, last bullet).
  6. 앱 사용 사례를 시뮬레이션하여 테스트 데이터를 생성하고 테스트 쿼리를 작성합니다. 필요한 경우 임의 문자열 생성기를 사용합니다.

MongoDB를 사용하여 큰 문서의 텍스트 쿼리에 문제가 있었습니다: 아포스트로피-cms의 자동 완성텍스트 검색 메모리 문제: 아이디어 필요

여기 샘플 데이터를 생성하기 위해 작성한 코드가 있습니다. 이 코드는 ApostropheCMS와 테스트 결과는 다음과 같습니다.

이것은 MongoDB 내부 문제라기보다는 데이터베이스 설계 문제입니다.저는 MongoDB가 이런 식으로 행동하도록 만들어졌다고 생각합니다.하지만 문서에 좀 더 명확한 설명을 하는 것이 많은 도움이 될 것입니다.

언급URL : https://stackoverflow.com/questions/23837906/mongodb-does-document-size-affect-query-performance

반응형