IT TIP

mongodb의 수많은 레코드에 대한 느린 페이지 매김

itqueen 2021. 1. 9. 11:14
반응형

mongodb의 수많은 레코드에 대한 느린 페이지 매김


Mongo의 한 컬렉션에 30 만 개가 넘는 레코드가 있습니다.

이 매우 간단한 쿼리를 실행할 때 :

db.myCollection.find().limit(5);

몇 밀리 초 밖에 걸리지 않습니다.

하지만 쿼리에서 건너 뛰기를 사용할 때 :

db.myCollection.find().skip(200000).limit(5)

아무것도 반환하지 않습니다 ... 몇 분 동안 실행되고 아무것도 반환하지 않습니다.

더 나은 방법?


MongoDB 문서에서 :

페이징 비용

안타깝게도 skip은 (매우) 비용이 많이 들고 데이터 페이지 (제한) 반환을 시작하기 전에 오프셋 / 건너 뛰기 위치에 도달하기 위해 서버가 컬렉션 또는 인덱스의 시작 부분부터 걸어 가야합니다. 페이지 번호가 증가함에 따라 스킵은 더 느려지고 CPU 집약적이며, 더 큰 컬렉션으로 인해 IO 바인딩이 될 수 있습니다.

범위 기반 페이징은 인덱스를 더 잘 사용하지만 특정 페이지로 쉽게 이동할 수는 없습니다.

스스로에게 질문해야합니다. 40000 페이지가 얼마나 자주 필요한가요? 기사 도 참조 하십시오.


이 문제에 대한 한 가지 접근 방식은 문서의 양이 많고이를 정렬 된 순서 로 표시하는 skip경우 (그렇지 않은 경우 얼마나 유용한 지 잘 모르겠습니다 ) 정렬하려는 키를 사용하여 결과의 다음 페이지.

따라서 시작하면

db.myCollection.find().limit(100).sort({created_date:true});

그런 다음 커서가 반환 한 마지막 문서 의 생성 날짜를 변수로 추출하면 max_created_date_from_last_result훨씬 더 효율적인 (인덱스가 있다고 가정 created_date) 쿼리로 다음 페이지를 얻을 수 있습니다.

db.myCollection.find({created_date : { $gt : max_created_date_from_last_result } }).limit(100).sort({created_date:true}); 

두 개념을 함께 결합하는 것이 효과적이라는 것을 알았습니다 (skip + limit 및 find + limit). skip + limit의 문제는 많은 문서 (특히 큰 문서)가있을 때 성능이 저하된다는 것입니다. find + limit의 문제는 임의의 페이지로 이동할 수 없다는 것입니다. 순차적으로하지 않고 페이지를 매길 수 있기를 원합니다.

내가 취하는 단계는 다음과 같습니다.

  1. 문서를 정렬하려는 방식에 따라 색인을 생성하거나 기본 _id 색인 (내가 사용한 것)을 사용합니다.
  2. 시작 값, 페이지 크기 및 이동하려는 페이지를 알고
  3. 프로젝트 + 건너 뛰기 + 시작해야하는 값 제한
  4. 페이지 결과 찾기 및 제한

16 개 레코드 중 5432 페이지 (자바 스크립트)를 얻으려면 대략 다음과 같이 보입니다.

let page = 5432;
let page_size = 16;
let skip_size = page * page_size;

let retval = await db.collection(...).find().sort({ "_id": 1 }).project({ "_id": 1 }).skip(skip_size).limit(1).toArray();
let start_id = retval[0].id;

retval = await db.collection(...).find({ "_id": { "$gte": new mongo.ObjectID(start_id) } }).sort({ "_id": 1 }).project(...).limit(page_size).toArray();

This works because a skip on a projected index is very fast even if you are skipping millions of records (which is what I'm doing). if you run explain("executionStats"), it still has a large number for totalDocsExamined but because of the projection on an index, it's extremely fast (essentially, the data blobs are never examined). Then with the value for the start of the page in hand, you can fetch the next page very quickly.

ReferenceURL : https://stackoverflow.com/questions/7228169/slow-pagination-over-tons-of-records-in-mongodb

반응형