View a markdown version of this page

인덱스 전용 스캔(적용된 쿼리) - Amazon DocumentDB

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

인덱스 전용 스캔(적용된 쿼리)

인덱스 전용 스캔(적용된 쿼리라고도 함)은 Amazon DocumentDB가 기본 문서를 읽지 않고 인덱스에 저장된 필드에서 쿼리에 완전히 응답하는 최적화입니다. 쿼리에 필요한 값이 인덱스에 이미 있으므로 Amazon DocumentDB는 일치하는 각 문서 가져오기를 건너뛰어 무작위 I/O를 방지하고 전체 문서를 읽는 비용을 디코딩할 수 있습니다. 쿼리 계획에서 인덱스 전용 스캔은 IXSCAN (인덱스 스캔) 또는 COLLSCAN (컬렉션 스캔) 대신 IXONLYSCAN 단계로 나타납니다. 이렇게 하면 I/O가 줄어들고 지원되는 쿼리의 쿼리 지연 시간이 크게 단축될 수 있습니다.

쿼리는 단일 인덱스에 모두 존재하는 소수의 필드만 터치할 때, 특히 문서 자체가 큰 경우 인덱스 전용 스캔의 좋은 후보입니다. 일반적인 예로는 대시보드, 분석 롤업 및 더 넓은 복합 인덱스에서 몇 가지 필드를 읽는 조회가 있습니다.

쿼리 결과는 인덱스 전용 스캔을 사용하든 사용하지 않든 동일합니다. 쿼리 계획과 수행하는 I/O의 양만 변경됩니다.

참고

인덱스 전용 스캔 지원은 Amazon DocumentDB 엔진 버전에 따라 다릅니다.

  • 필드가_id 아닌 2개 이상의 가려진 find 프로젝션에는 엔진 버전 8.0.2 이상이 필요합니다. 이전 버전에서는 커버드 find 프로젝션에 필드가 아닌_id 필드가 하나 이상 포함될 수 있습니다. 둘 이상의 필드가 있는 프로젝션은 정상 인덱스 스캔 또는 컬렉션 스캔으로 돌아갑니다.

  • 적용 대상와 같은 집계 파이프라인에 대한 인덱스 전용 스캔에는 엔진 버전 8.0.2 이상이 $group필요합니다.

Amazon DocumentDB가 인덱스 전용 스캔을 사용하는 경우

Amazon DocumentDB는 단일 인덱스에 작업이 읽는 모든 필드가 포함된 경우 다음 작업에 대한 인덱스 전용 스캔을 고려합니다.

커버드 find 프로젝션

find 쿼리는 프로젝션이 하나 이상의 최상위 필드를 단순하게 포함하고 모든 프로젝션된 필드가 단일 인덱스에 있는 경우를 검증합니다. 예를 들어의 복합 인덱스가 주어지면 { customerId: 1, status: 1, total: 1 }다음 쿼리가 포함됩니다. 세 개의 프로젝션된 필드는 모두 인덱스에 있으며 _id 명시적으로 제외됩니다. (필드_id가 아닌 필드가 두 개 이상인 프로젝션을 관리하려면 엔진 버전 8.0.2 이상이 필요합니다.)

db.orders.createIndex({ customerId: 1, status: 1, total: 1 }) db.orders.find( { customerId: 42 }, { _id: 0, customerId: 1, status: 1, total: 1 } )

우승 계획은 IXONLYSCAN 스테이지를 사용하며 스토리지에서 일치하는 문서를 가져오지 않습니다.

{ "stage": "IXONLYSCAN", "indexName": "customerId_1_status_1_total_1", "direction": "forward", "indexCond": { "$and": [ { "customerId": { "$eq": 42 } } ] } }
참고

적용 대상 find 쿼리에서 결과의 필드는 프로젝션에 나열된 순서 또는 문서에 저장된 순서가 아닌 인덱스 순서(필드가 인덱스 정의에 표시되는 순서)로 반환됩니다. 이는 해당 쿼리에 대한 MongoDB 동작과 일치합니다. 컬렉션 스캔으로 응답되는 쿼리는 대신 저장 문서 순서로 필드를 반환합니다.

적용 $group 집계

$group 스테이지는 일반적으로 몇 개의 필드(그룹 키 및 해당 누적기에 대한 입력)만 읽지만 선행 없이 실행되는 경우가 많습니다$match. 커버링 인덱스가 없으면 Amazon DocumentDB는 컬렉션의 모든 전체 문서를 읽고 디코딩하여 해당 몇 개의 필드를 그룹화에 공급하기만 합니다.

포함된 $group 단계를 포함한 집계 파이프라인에 대한 인덱스 전용 스캔은 엔진 버전 8.0.2 이상에서 사용할 수 있습니다.

단일 인덱스에 파이프라인 접두사가 읽는 모든 필드가 포함된 경우 Amazon DocumentDB는 그룹 아래에 인덱스 전용 스캔을 배치하고 인덱스에서 직접 해당 필드를 읽을 수 있습니다. 에 복합 인덱스를 사용하여 상태별로 주문을 그룹화하고 합계를 합산하는 파이프라인을 생각해 보세요. { status: 1, total: 1 }

db.orders.createIndex({ status: 1, total: 1 }) db.orders.aggregate([ { $group: { _id: "$status", revenue: { $sum: "$total" } } } ])

파이프라인은 인덱스에 total있는 status 및 만 읽으므로 그룹은 컬렉션 스캔 IXONLYSCAN 대신에서 공급됩니다.

// Without a covering index $group <- COLLSCAN (reads and decodes every full document) // With a covering index on { status, total } $group <- IXONLYSCAN over { status, total } (reads only the referenced fields)

앞에 $match, $skip, 또는 $sort$limit가 지원$group됩니다. 그러나 파이프라인이 포함되려면 이러한 단계가 참조하는 모든 필드(예: $match 필터 필드 또는 $sort 키)도 동일한 인덱스에 있어야 합니다. 인덱스에서 참조된 필드가 누락된 경우 Amazon DocumentDB는 컬렉션 또는 인덱스 스캔으로 돌아갑니다.

참고

find 프로젝션과 달리 에는 문서가 암시적으로 포함되지 $group 않습니다_id. _id의 $group는 문서 식별자가 아닌 그룹 키이므로 인덱스에 파이프라인을 덮_id기 위해 문서를 포함할 필요가 없습니다.

적용 대상 쿼리에 대한 요구 사항

Amazon DocumentDB가 인덱스 전용 스캔을 사용하려면 다음을 모두 포함해야 합니다.

  • 단일 인덱스에는 쿼리가 읽는 모든 필드가 포함됩니다. 여기에는의 프로젝션된 필드find와 그룹 키, 누산기 입력, 해당 $group 파이프라인의 필터 또는 정렬 필드가 포함됩니다. 인덱스에 필드가 하나도 없는 경우 쿼리를 덮을 수 없습니다.

  • 프로젝션에는 최상위 필드(용)가 포함됩니다find. 제외 프로젝션, 계산된 필드 및 $slice 및와 같은 프로젝션 연산$elemMatch자는 사용할 수 없습니다.

  • _id 필드가 고려됩니다(의 경우find). _id는 기본적으로 포함되므로와 같은 일반적인 복합 인덱스{ a: 1, b: 1 }는 find({}, { a: 1, b: 1 })를 다루지 않습니다. 암시적 _id는 인덱스에 없습니다. 프로젝션_id에서 제외하거나({ _id: 0, a: 1, b: 1 }) 인덱스_id에를 추가합니다.

  • 필터는 인덱스에 의해 완전히 충족됩니다. Amazon DocumentDB는 쿼리 조건자의 일부를 인덱스 바인딩으로 변환할 수 없는 경우 해당 부분을 잔차 필터로 유지하고, 문서를 읽어 평가하며, 스캔을 인덱스 전용 스캔으로 변환하지 않습니다. $mod, $ne, $nin, 등의 연산자는 잔차 필터를 $exists 남깁니다.

  • 프로젝션된 필드는 멀티키(배열) 열이 아닙니다. 제한 사항 섹션을 참조하세요.

제한 사항

다음 경우에는 인덱스 전용 스캔을 사용할 수 없으며 정상 인덱스 스캔 또는 컬렉션 스캔으로 돌아갑니다. 이는 예상되는 동작이며 결과의 정확성에 영향을 미치지 않습니다.

  • 멀티키(배열) 필드. 필드에 어떤 문서에든 배열 값이 있는 경우 해당 인덱스 열은 멀티키입니다. 멀티키 인덱스는 배열 요소당 하나의 항목을 저장하므로 인덱스에서 원래 배열을 재구성할 수 없습니다. 이러한 필드를 읽는 쿼리는 다루지 않습니다.

  • 점선 또는 중첩 경로. 인덱스에 해당 경로가 포함되어 있더라도와 같은 중첩 경로의 프로젝션 또는 필드 참조"address.city"는 사용할 수 없습니다.

  • 제외, 계산된 또는 연산자 프로젝션. { b: 0 }, { total: { $add: ["$price", "$tax"] } }또는와 같은 프로젝션에는 전체 문서가 { a: { $slice: 5 } } 필요하며 적용되지 않습니다.

  • 집계의 전체 문서 참조입니다. 전체 문서를 참조$group하는는 인덱스가 전체 문서를 재구성할 수 없으므로(예: { $push: "$$ROOT" }) 다룰 수 없습니다.

  • 이전 단계 재구성$group. 가 파이프라인의 적용 자격을 $group 상실하기 전에 나타나는 문서(예: $project, $addFields$unwind, 또는 $lookup)를 재구성하는 단계입니다.

  • 문자열 조건자의 데이터 정렬 불일치. 쿼리의 데이터 정렬이 인덱스의 데이터 정렬과 다르면 인덱스에서 문자열 조건자를 제공할 수 없으며 문서 가져오기를 강제하는 잔차 필터를 남깁니다. 숫자 및 유형 기반 조건자는 영향을 받지 않습니다.

인덱스 전용 스캔 확인

explain("executionStats") 출력을 사용하여 쿼리가 인덱스 전용 스캔에서 제공되고 문서에 접촉하지 않는지 확인합니다. 다음 두 가지를 찾습니다.

  • 이기는 계획은 IXONLYSCAN 스테이지를 사용합니다.

  • 해당 단계의 docsExamined 값은 0 (및 0)totalDocsExamined이며, 이는 문서를 읽지 않고 쿼리가 인덱스에서 완전히 응답되었음을 의미합니다.

db.orders.find( { customerId: 42 }, { _id: 0, customerId: 1, status: 1, total: 1 } ).explain("executionStats").executionStats
{ "executionSuccess": true, "nReturned": "2", "executionTimeMillis": "0.714", "totalDocsExamined": "0", "executionStages": { "stage": "IXONLYSCAN", "nReturned": "2", "indexName": "customerId_1_status_1_total_1", "direction": "forward", "docsExamined": "0" } }
참고

IXONLYSCAN 단계의 0이 아닌 docsExamined 값은 인덱스에 데이터가 포함되어 있음을 의미하지만 Amazon DocumentDB는 여전히 스토리지를 확인하여 각 문서 버전이 표시되는지 확인했습니다. 이는 컬렉션에 더 이상 사용되지 않는 문서 버전 가비지 컬렉션이 아직 회수되지 않은 최근 쓰기가 있는 경우 발생할 수 있습니다. 가비지 수집이 해당 문서를 처리하면가 로 docsExamined 삭제됩니다0. 이때 쿼리는 적용 스캔의 모든 이점을 실현합니다. 가비지 수집에 대한 자세한 내용은 섹션을 참조하세요Amazon DocumentDB의 폐영역 회수. docsExamined 지표에 대한 자세한 내용은 쿼리 계획 분석를 참고하세요.

모범 사례

  • 가장 빈번한 쿼리 프로젝트 또는 그룹이 있는 필드가 포함된 복합 인덱스를 설계하여 해당 쿼리를 처리할 수 있습니다.

  • _id가 커버링 인덱스의 일부가 아닌 한 find 프로젝션({ _id: 0, ... })_id에서 제외합니다.

  • 다중 키 열은 인덱스 전용 경로를 부적격화하므로 쿼리를 다루려는 경우 배열(멀티키) 필드를 인덱싱하지 마십시오.

  • 포함된 스캔이 문서 액세스를 건너뛰고를 docsExamined 유지하도록 가비지 수집이 쓰기 워크로드를 따라잡도록 허용합니다0. 자세한 내용은 Amazon DocumentDB의 폐영역 회수 섹션을 참조하세요.