쿼리 성능 최적화

느린 쿼리 문제를 해결하려면 Query Explain 을 사용하여 쿼리 실행 계획과 런타임 실행 프로필을 가져옵니다. 다음 섹션에서는 실행 프로필에 따라 쿼리 성능을 최적화하기 위해 취할 수 있는 단계를 설명합니다.

결과 수 제한

실행 트리에서 반환된 레코드 필드를 사용하여 쿼리가 많은 문서를 반환하는지 확인합니다. limit(...) 단계를 사용하여 반환되는 문서 수를 제한하는 것이 좋습니다. 이렇게 하면 네트워크를 통해 클라이언트에 반환될 때 결과의 직렬화된 바이트 크기가 줄어듭니다. Limit 노드 앞에 MajorSort 노드가 있는 경우 쿼리 엔진은 LimitMajorSort 노드를 병합하고 전체 인메모리 구체화 및 정렬을 TopN 정렬로 대체하여 쿼리의 메모리 요구사항을 줄일 수 있습니다.

결과 문서 크기 제한

select(...)를 사용하여 필요한 필드만 반환하거나 remove_fields(...)를 사용하여 너무 큰 필드를 삭제하여 반환되는 문서의 크기를 제한하는 것이 좋습니다. 이렇게 하면 중간 결과 처리의 컴퓨팅 및 메모리 비용과 네트워크를 통해 클라이언트에 반환될 때 결과의 직렬화된 바이트 크기를 줄일 수 있습니다. 쿼리에서 참조되는 모든 필드가 일반 색인으로 처리되는 경우 쿼리가 색인 검색으로 완전히 처리되어 기본 스토리지에서 문서를 가져올 필요가 없습니다.

색인 사용

다음 안내에 따라 색인을 설정하고 최적화하세요.

쿼리에서 색인을 사용하고 있는지 확인

실행 트리의 리프 노드를 확인하여 쿼리에서 색인을 사용하고 있는지 확인할 수 있습니다. 실행 트리의 리프 노드가 TableScan 노드인 경우 쿼리가 색인을 사용하지 않고 기본 스토리지에서 문서를 스캔하고 있음을 의미합니다. 색인이 사용 중인 경우 실행 트리의 리프 노드에 색인의 색인 ID와 색인 필드가 표시됩니다.

더 나은 색인 식별

색인은 쿼리 엔진이 기본 스토리지에서 가져와야 하는 문서 수를 줄일 수 있거나 필드 순서가 쿼리의 정렬 요구사항을 충족할 수 있는 경우 쿼리에 유용합니다.

쿼리에 색인이 사용되지만 쿼리 엔진이 여전히 많은 문서를 가져와서 삭제하는 경우(많은 레코드를 반환하는 스캔 노드와 적은 레코드를 반환하는 필터 노드로 식별됨) 색인을 사용하여 충족된 쿼리 조건자가 선택적이지 않다는 신호입니다. 더 적합한 색인을 만들려면 색인 만들기를 참고하세요.

쿼리에 색인이 사용되지만 쿼리 엔진이 여전히 쿼리 실행 트리의 MajorSort 노드로 식별되는 결과 집합의 메모리 내 재정렬을 실행하는 경우, 이는 사용된 색인이 쿼리의 정렬 요구사항을 제공하는 데 사용될 수 없다는 신호입니다. 더 적합한 색인을 만들려면 다음 섹션을 참고하세요.

색인 만들기

색인 관리 문서를 따라 색인을 만듭니다. 쿼리에서 색인을 사용할 수 있도록 하려면 다음 순서로 필드가 있는 일반(멀티 키 아님) 색인을 만드세요.

  1. 등호 연산자에 사용될 모든 필드입니다. 쿼리 간 재사용 가능성을 극대화하려면 쿼리 간 등호 연산자에서 필드가 발생하는 빈도의 내림차순으로 필드를 정렬합니다.
  2. 정렬할 모든 필드(동일한 순서)입니다.
  3. 범위 또는 부등호 연산자에 사용될 필드입니다(쿼리 제약 조건 선택성의 내림차순).
  4. 색인의 쿼리 일부로 반환될 필드: 색인에 이러한 필드를 포함하면 색인이 쿼리를 처리하고 기본 스토리지에서 문서를 가져오지 않아도 됩니다.

색인 또는 테이블 스캔 강제 실행

기본 모드에서 Firestore를 쿼리하면 쿼리 효율을 높일 수 있는 모든 색인이 자동으로 사용됩니다. 따라서 쿼리에 색인을 지정할 필요가 없습니다. 하지만 워크로드에 중요한 쿼리의 경우 보다 일관된 성능을 위해 forceIndex 옵션을 사용하는 것이 좋습니다.

일부의 경우 기본 모드에서 Firestore가 쿼리 지연 시간을 증가시키는 색인을 선택할 수도 있습니다. 성능 회귀 문제해결 단계를 따르고 쿼리에 다른 색인을 시도했는지 확인한 경우 forceIndex 옵션을 사용하여 색인을 지정할 수 있습니다.

파이프라인 작업의 모든 입력 단계에서 forceIndex 옵션을 사용하여 기본 모드에서 Firestore의 기본 쿼리 계획을 재정의하고 사용할 색인을 지정하거나 테이블 스캔을 강제 실행할 수 있습니다.

특정 색인 강제 실행

쿼리에서 특정 색인을 사용하도록 강제 실행하려면 색인 ID를 문자열로 forceIndex 옵션에 제공합니다. 색인 ID는 콘솔 또는 오류 메시지에서 확인할 수 있습니다.

다음 예에서는 플래너가 ID가 CICAgOi36pgK인 색인을 사용하도록 강제 실행합니다.

Node.js
// Force Planner to use Index ID CICAgOi36pgK
await db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" })
  .limit(100)
  .execute();
자바
// Force Planner to use Index ID CICAgOi36pgK
Pipeline.Snapshot results1 =
    firestore.pipeline()
      .collectionGroup("customers", new CollectionGroupOptions()
          .withHints(new CollectionHints().withForceIndex("CICAgOi36pgK")))
      .limit(100)
      .execute().get();
Go
// Force Planner to use Index ID CICAgOi36pgK
snapshot1 := client.Pipeline().
	CollectionGroup("customers", firestore.WithForceIndex("CICAgOi36pgK")).
	Limit(100).
	Execute(ctx)

다음은 특정 색인을 강제 실행하는 몇 가지 사용 사례입니다.

  • 다양한 색인의 성능 테스트
  • 쿼리에 특정 최적 색인이 사용되도록 보장
  • 기본 선택이 특정 쿼리에 최적이 아닌 경우 최적화 도구 재정의

지정된 색인을 찾을 수 없으면 쿼리가 실패합니다.

테이블 스캔 강제 실행

테이블 스캔은 보조 색인을 사용하지 않고 컬렉션 또는 컬렉션 그룹의 문서를 읽습니다. 테이블 스캔을 강제 실행하려면 forceIndexprimary로 설정합니다.

다음 예에서는 테이블 스캔을 강제 실행합니다.

// Force Planner to only do a Full-Table Scan
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "primary" })
  .limit(100)

다음과 같은 경우에 테이블 스캔을 사용할 수 있습니다.

  • 색인 오버헤드가 정당화되지 않는 매우 작은 컬렉션의 경우
  • 컬렉션의 대부분의 문서에 액세스하는 쿼리의 경우
  • 디버깅 및 성능 비교의 경우

Query Explain과 함께 forceIndex 사용

Query Explain, 특히 analyze 옵션을 사용하여 forceIndex의 효과를 관찰할 수 있습니다.

  • 실행 트리의 리프 노드에서 색인 ID를 확인하여 기본 모드에서 Firestore가 forceIndex에 지정된 색인을 사용했는지 확인합니다.
  • TableScan 노드가 forceIndex: "primary"를 사용하는 경우 계획에 표시되는지 확인합니다.
  • 지연 시간, 스캔된 문서, 스캔된 색인 항목과 같은 성능 측정항목을 forceIndex가 있는 경우와 없는 경우를 비교하여 쿼리 성능을 미세 조정합니다.

forceIndex 관련 권장사항

forceIndex를 사용하면 쿼리 실행을 더 세부적으로 제어할 수 있지만 기본 모드에서 Firestore의 쿼리 최적화 도구는 일반적으로 대부분의 사용 사례에 효율적입니다. forceIndex를 사용할 때는 다음 권장사항을 고려하세요.

  • forceIndex를 신중하게 사용합니다. 기본 쿼리 계획으로 최적의 성능을 얻지 못하는 경우 색인을 강제 실행하기 전에 Query Explain을 사용하여 문제를 진단합니다.
  • forceIndex를 사용할 때는 실제 데이터 볼륨으로 쿼리를 테스트하여 성능 및 비용 특성을 파악해야 합니다.
  • 프로덕션 환경의 대규모 컬렉션에서 forceIndex: "primary"를 사용하지 마세요.