Firestore에 많은 문서를 쓰는 가장 빠른 방법은 무엇입니까?


답변:


26

TL; DR : Firestore에서 대량 날짜 생성을 수행하는 가장 빠른 방법은 병렬 개별 쓰기 작업을 수행하는 것입니다.

Firestore에 1,000 개의 문서를 쓰려면 다음이 필요합니다.

  1. ~105.4s 순차적 인 개별 쓰기 작업을 사용하는 경우
  2. ~ 2.8s (2) 일괄 쓰기 작업을 사용하는 경우
  3. ~ 1.5s 병렬 개별 쓰기 작업을 사용하는 경우

Firestore에서 많은 수의 쓰기 작업을 수행하는 일반적인 세 ​​가지 방법이 있습니다.

  1. 각 개별 쓰기 작업을 순서대로 수행하십시오.
  2. 일괄 쓰기 작업 사용
  3. 개별 쓰기 작업을 병렬로 수행합니다.

무작위 문서 데이터 배열을 사용하여 아래에서 차례로 살펴 보겠습니다.


개별 순차 쓰기 작업

이것이 가장 간단한 해결책입니다.

async function testSequentialIndividualWrites(datas) {
  while (datas.length) {
    await collection.add(datas.shift());
  }
}

모든 문서를 작성할 때까지 각 문서를 차례로 작성합니다. 다음 쓰기를 시작하기 전에 각 쓰기 작업이 완료 될 때까지 기다립니다.

이 방법을 사용하면 1,000 개의 문서를 작성하는 데 약 105 초가 걸리므로 처리량은 초당10 개의 문서 쓰기입니다 .


일괄 쓰기 작업 사용

가장 복잡한 솔루션입니다.

async function testBatchedWrites(datas) {
  let batch = admin.firestore().batch();
  let count = 0;
  while (datas.length) {
    batch.set(collection.doc(Math.random().toString(36).substring(2, 15)), datas.shift());
    if (++count >= 500 || !datas.length) {
      await batch.commit();
      batch = admin.firestore().batch();
      count = 0;
    }
  }
}

BatchedWrite을 호출 하여 객체를 생성 batch()하고 최대 500 개의 문서 용량까지 채운 다음 Firestore에 씁니다. 우리는 각 문서에 상대적으로 고유 할 가능성이있는 생성 된 이름을 부여합니다 (이 테스트에는 충분합니다).

이 방법을 사용하면 1,000 개의 문서를 작성하는 데 약 2.8 초가 걸리므로 처리량은 초당357 개의 문서 쓰기입니다 .

순차적 인 개별 쓰기보다 훨씬 빠릅니다. 실제로 : 많은 개발자들이이 방법을 사용하는 것이 가장 빠르다고 생각하기 때문에이 방법을 사용하지만 위의 결과에서 이미 알 수 있듯이 이것은 사실이 아닙니다. 그리고 배치에 대한 크기 제약으로 인해 코드가 훨씬 복잡합니다.


병렬 개별 쓰기 작업

Firestore 설명서에는 많은 데이터를 추가 하는 성능에 대해 다음 과 같이 나와 있습니다 .

대량 데이터 입력의 경우 병렬화 된 개별 쓰기가있는 서버 클라이언트 라이브러리를 사용하십시오. 배치 된 쓰기는 직렬화 된 쓰기보다 성능이 우수하지만 병렬 쓰기보다 성능이 좋지 않습니다.

다음 코드를 사용하여 테스트 할 수 있습니다.

async function testParallelIndividualWrites(datas) {
  await Promise.all(datas.map((data) => collection.add(data)));
}

이 코드는 add가능한 빨리 작업을 시작한 다음 작업 Promise.all()이 끝날 때까지 기다립니다. 이 방법을 사용하면 작업을 병렬로 실행할 수 있습니다.

이 방법을 사용하면 1,000 개의 문서를 작성하는 데 약 1.5 초가 걸리므로 처리량은 초당667 개의 문서 쓰기입니다 .

차이점은 처음 두 접근 방식만큼 크지는 않지만 배치 쓰기보다 1.8 배 이상 빠릅니다.


몇 가지 참고 사항 :

  • 이 테스트의 전체 코드는 Github 에서 찾을 수 있습니다 .
  • 테스트는 Node.js로 수행되었지만 Admin SDK가 지원하는 모든 플랫폼에서 유사한 결과를 얻을 수 있습니다.
  • 그러나 결과가 매우 다르고 예측하기가 어려울 수 있으므로 클라이언트 SDK를 사용하여 대량 삽입을 수행하지 마십시오.
  • 일반적으로 실제 성능은 컴퓨터, 인터넷 연결의 대역폭 및 대기 시간 및 기타 여러 요인에 따라 다릅니다. 그 순서에 따라 순서가 동일 할 것으로 예상되지만 그 차이에 따라 차이가있을 수도 있습니다.
  • 자체 테스트에 특이 치가 있거나 완전히 다른 결과를 찾는 경우 아래에 의견을 남겨주십시오.
  • 배치 쓰기는 원자 적입니다. 따라서 문서간에 종속성이 있고 모든 문서를 작성해야하거나 문서를 작성하지 않아야하는 경우 일괄 쓰기를 사용해야합니다.

1
이것은 매우 흥미 롭습니다. 작업을 해 주셔서 감사합니다! OOC, 일괄 쓰기 작업을 병렬로 테스트 했습니까? 분명히이 경우 문서가 두 배치에 모두 들어 가지 않도록해야합니다.
robsiemb

1
병렬 배치 쓰기를 테스트하려고했지만 할당량이 부족했습니다 (무료 프로젝트이므로 업그레이드하기에는 너무 게으른 것입니다). 오늘은 또 다른 날이므로 시도해보고 중요한 경우 답변을 업데이트 할 수 있습니다.
Frank van Puffelen

2
@robsiemb 방금 병렬 배치 쓰기로 테스트했습니다. 성능은 개별 병렬 쓰기와 매우 유사하므로 테스트에서 처음으로 묶여 있다고 말하고 싶습니다. 백엔드에서 처리되는 특성으로 인해 일괄 쓰기가 더 빨리 저하 될 수 있습니다. 훨씬 더 복잡한 코드와 결합하여 아직 인식되지 않았지만 존재하지 않는 성능 이점이 아닌 원자성에 만 코드를 사용하는 것이 좋습니다.
Frank van Puffelen

@FrankvanPuffelen 병렬화 된 쓰기는 "문서를 추가"하는 대신 문서를 "설정"하면 더 빠릅니다. db.collection ( 'cities'). add (data) 대신 db.collection ( 'cities'). doc ( 'LA'). set (data)
alek6dj

호출 add()은 고유 ID (순전히 클라이언트 측)를 생성 한 다음 set()작업을 수행하는 것 이상입니다. 따라서 결과는 동일해야합니다. 그것이 당신이 관찰 한 것이 아니라면, 당신이 시도한 것을 재현하는 최소한의 사례로 새로운 질문을 게시하십시오.
Frank van Puffelen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.