View a markdown version of this page

캐시 필터 계획 - Amazon DocumentDB

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

캐시 필터 계획

인덱스 필터라고도 하는 계획 캐시 필터는 쿼리 플래너가 특정 쿼리 셰이프에 대해 고려할 수 있는 인덱스 세트를 제한합니다. 쿼리가 필터가 있는 셰이프와 일치하면 플래너는 컬렉션의 모든 인덱스를 평가하는 대신 해당 필터에 이름이 지정된 인덱스에서만 계획을 선택합니다.

쿼리 셰이프는 조건자 값이 정규화된 쿼리 조건자, 정렬 사양 및 컬렉션 네임스페이스의 조합입니다. 값만 다른 두 쿼리는 셰이프를 공유하므로 단일 필터가 모든 쿼리를 포괄합니다. 의 출력에서 planCacheListFilters정규화된 값은 로 표시됩니다"@".

계획 캐시 필터를 사용하면 계획을 고정할 수 있으므로 데이터 배포 또는 인덱스 변경으로 인해 느린 인덱스를 선택하지 않아도 됩니다. 필터의 속성은 다음과 같습니다.

  • 애플리케이션 변경은 필요하지 않습니다. 필터는 데이터베이스 명령으로 설정되고 서버에 적용되므로 코드 배포 없이 회귀를 완화할 수 있습니다. 이는 모든 호출 사이트에 추가해야 hint하는와 주요 차이점입니다.

  • 범위는 하나의 쿼리 셰이프입니다. 셰이프는 전체 쿼리가 아닌 컬렉션, 조건자 및 정렬에 의해 정의되므로 필터는 해당 셰이프와 일치하는 쿼리만 제한합니다. 동일한 컬렉션에 대한 다른 쿼리는 정상적으로 계속 계획됩니다.

  • 변경 사항은 내구성이 뛰어납니다. 필터는 인스턴스 재시작 및 엔진 패치 적용 전반에 걸쳐 유지됩니다. 컬렉션을 삭제하면 필터가 제거됩니다.

  • 변경 사항은 되돌릴 수 있습니다. 필터를 지우면 셰이프가 일반적인 비용 기반 계획으로 반환되므로 기본 원인을 조사하는 동안 워크로드를 안정화할 수 있는 위험이 낮은 방법입니다.

지원되는 명령

계획 캐시 필터에는 플래너 버전 2.0 이상이 필요합니다. 필터를 적용할 수 있는 명령은 다음 표와 같이 플래너 버전과 Amazon DocumentDB 마이너 버전에 따라 달라집니다.

계획 캐시 필터에 대한 명령 지원
명령 최소 플래너 버전 최소 마이너 버전

find

2.0

5.0.0, 8.0.0

count

2.0

5.0.0, 8.0.0

update

2.0

5.0.2, 8.0.2

delete

2.0

5.0.2, 8.0.2

findAndModify

2.0

5.0.2, 8.0.2

distinct

3.0

8.0.0

aggregate

3.0

8.0.2

참고

플래너 버전 3.0은 Amazon DocumentDB 8.0에서만 사용할 수 있습니다. distinct 및 aggregate 명령에는 플래너 버전 3.0이 필요하므로 이러한 두 명령에 대한 계획 캐시 필터는 Amazon DocumentDB 8.0에서만 사용할 수 있습니다. 플래너 버전 2.0을 지원하는 Amazon DocumentDB 5.0에서는 필터가 find, count, update, delete및 findAndModify 명령에 적용됩니다.

aggregate 명령의 경우 셰이프는 파이프라인 전면에서 가져옵니다. 선행는 필터를 $match 제공하고,는 정렬을 제공한 $sort 직후를 제공합니다. $skip와는 셰이프에 영향을 $limit 주지 않으며,는 해당 지점 이후의 단계를 수행하지 않습니다.

Amazon DocumentDB는 계획하기 전에 파이프라인을 최적화하고 계획 캐시 필터를 최적화된 파이프라인과 일치시킵니다. 따라서 플래너가 보는 필터와 정렬은 작성한 단계와 다를 수 있습니다. 예를 들어 파이프라인 앞에 있는 두 개의 인접 $match 단계가 단일 $and 조건자로 결합됩니다.

db.orders.aggregate([ { $match: { status: "SHIPPED" } }, { $match: { region: "us-east-1" } }, { $group: { _id: "$customerId", total: { $sum: "$amount" } } } ])

플래너는 $match에 하나를 표시{$and: [{status: ...}, {region: ...}]}하므로 필터를 결합된 조건자에 설정해야 합니다.

db.runCommand({planCacheSetFilter: "orders", query: { $and: [ { status: "SHIPPED" }, { region: "us-east-1" } ] }, indexes: [ "status_1_region_1" ]})

$lookup 또는 $graphLookup 단계의 외래 컬렉션에 설정된 필터는 해당 외래 컬렉션을 스캔하는 데 사용되는 인덱스를 구동합니다.

지원되는 쿼리 셰이프

Amazon DocumentDB 5.0.2 및 8.0.2부터 계획 캐시 필터가 있는 쿼리 셰이프에 다음 연산자가 나타날 수 있습니다.

  • $text. 검색 문자열이 정규화되므로 검색하는 용어만 다른 쿼리는 하나의 셰이프를 공유합니다.

  • $near 및 $nearSphere. 두 연산자 모두 동일한 셰이프로 정규화됩니다. 좌표, $minDistance및 $maxDistance는 셰이프의 일부가 아닙니다.

  • $geoWithin 및 $geoIntersects. GeoJSON 지오메트리 유형은 셰이프의 일부이므로 Polygon 쿼리와 MultiPolygon 쿼리는 다른 셰이프입니다. 좌표는 셰이프의 일부가 아닙니다.

  • $regex, 필드에서 직접 사용하는 경우. 패턴 및 옵션이 정규화되므로 동일한 필드의 모든 정규 표현식은 하나의 셰이프를 공유합니다.

$jsonSchema, $expr또는를 사용하는 쿼리 셰이프에 대한 오류 코드 303과 함께 필터 설정이 실패합니다$sampleRate. 다음 셰이프에 대해서도 실패합니다. 이러한 쿼리를 사용하는 쿼리는 필터 없이 계획됩니다.

  • $in, $nin또는 내에 $regex 중첩된 $all. 정규식을 리터럴 값과 혼합하는 배열은 인덱스에 대해 평가할 수 없으므로 해당 셰이프의 필터는 적용할 수 없습니다.

  • 의 정렬 사양입니다{$natural: 1}. $natural 정렬은 플래너를 인덱스로 제한하는 것과 호환되지 않는 컬렉션 스캔을 요청합니다.

필터 설정, 나열 및 지우기

계획 캐시 필터를 설정하려면 planCacheSetFilter 명령을 사용합니다. query 및 sort 필드는 함께 쿼리 셰이프를 지정하고 플래너가 해당 셰이프에 대해 고려할 수 있는 인덱스 이름을 indexes 나열합니다.

db.runCommand({ planCacheSetFilter: <collection>, query: <query>, sort: <sort>, // optional indexes: [ <index1>, <index2>, ...], comment: <any> // optional })

예를 들어 다음 명령은 플래너를 정렬 없이 셰이프의 a_1 인덱스{a: {$eq: "@"}, b: {$eq: "@"}}로 제한합니다.

db.runCommand({planCacheSetFilter: "foo", query: { a: 1, b: 1 }, sort: {}, indexes: [ "a_1" ]})

이미 있는 셰이프에 대한 필터를 설정하면 기존 필터가 대체됩니다. 다음 두 명령을 실행한 후 셰이프의 필터는 {a: {$eq: "@"}, b: {$eq: "@"}}입니다["b_1"].

db.runCommand({planCacheSetFilter: "foo", query: { a: 1, b: 1 }, sort: {}, indexes: [ "a_1" ]}) db.runCommand({planCacheSetFilter: "foo", query: { a: 6, b: 10 }, sort: {}, indexes: [ "b_1" ]})

컬렉션의 모든 필터를 나열하려면 planCacheListFilters 명령을 사용합니다.

db.runCommand({planCacheListFilters: <collection>})

출력에는 정규화된 값과 허용된 인덱스 목록이 있는 저장된 각 셰이프가 표시됩니다.

{ "filters" : [ { "query" : { "a" : { "$eq" : "@" } }, "sort" : { }, "indexes" : [ "a_1" ] }, { "query" : { "a" : { "$gt" : "@" } }, "sort" : { "a" : 1 }, "indexes" : [ "a_1_b_1" ] } ], "ok" : 1 }

연산자는 보존되며 값만 로 대체됩니다"@". 와 같은 암시적 동등성{a: 1}은 명시적 형식인 로 나열{"a": {"$eq": "@"}}되며 $in 배열의 요소는 전체적으로 로 대체됩니다{"a": {"$in": "@"}}. 정렬이 없는 필터 세트는 빈 sort 문서와 함께 나열됩니다.

필터를 제거하려면 planCacheClearFilters 명령을 사용합니다.

db.runCommand({ planCacheClearFilters: <collection>, query: <query pattern>, // optional sort: <sort specification>, // optional comment: <any> // optional })

컬렉션의 모든 필터를 지우려면 query 및를 모두 생략합니다sort.

db.runCommand({planCacheClearFilters: "foo"})

query 및를 모두 제공하면 정확한 정렬이 있는 필터만 sort지워집니다. 의 값은 query 정규화되므로 모든 대표 값이 작동합니다. 정렬 없이 설정된 필터만 지우려면 빈 sort 문서를 전달합니다.

db.runCommand({planCacheClearFilters: "foo", query: {a: 1}, sort: {a: 1}}) db.runCommand({planCacheClearFilters: "foo", query: {a: 1}, sort: {}})

필터가 적용되었는지 확인

explain 출력에는 계획 캐시 필터 상태를 보고하는 두 개의 필드가 포함됩니다.

  • indexFilterSet는 쿼리 셰이프에 대한 컬렉션에 필터가 있는 true 경우입니다.

  • indexFilterApplied는 해당 필터 목록의 인덱스를 사용하여 쿼리를 계획한 true 경우에만 입니다.

Amazon DocumentDB 5.0.2 및 8.0.2부터 이러한 필드는 계획 캐시 필터를 지원하는 모든 명령과 해당 명령의 프로파일러 출력에 보고됩니다. 이전 마이너 버전에서는 find 명령에 대해서만 보고되었습니다. 설명 출력 읽기에 대한 자세한 내용은 섹션을 참조하세요쿼리 계획 분석.

필터는 적용하지 않고 쿼리 셰이프와 일치할 수 있습니다. 필터 목록의 인덱스 중 어느 것도 쿼리를 처리할 수 없는 경우 플래너는 필터 없이 계획을 다시 세우고 비용에 대한 인덱스를 선택합니다. 이 경우 indexFilterSet는 true 이고는 indexFilterApplied입니다false. 이는 명명된 인덱스가 쿼리의 필드를 다루지 않거나, 명명된 인덱스가 존재하지 않거나, $regex셰이프가 고정되지 않았거나 대/소문자를 구분하지 않는 패턴과 같은 인덱스 경계를 생성할 수 없는 경우에 발생합니다.

예제

다음 예제에서는 컬렉션orders과이 $lookup 예제의 customers 컬렉션을 이러한 인덱스와 함께 사용합니다.

db.orders.createIndex({ status: 1 }) // status_1 db.orders.createIndex({ status: 1, orderDate: 1 }) // status_1_orderDate_1 db.orders.createIndex({ customerId: 1 }) // customerId_1 db.customers.createIndex({ customerId: 1 }) // customerId_1

예: find 쿼리를 복합 인덱스에 고정

를 필터링status하고를 정렬하는 쿼리를 생각해 보십시오. orderDate

db.orders.find({ status: "SHIPPED" }).sort({ orderDate: 1 })

복합 인덱스는 조건자와 정렬을 모두 status_1_orderDate_1 충족하므로 별도의 정렬이 필요하지 않습니다. 플래너가 대신를 선택하는 경우 status_1쿼리는 결과를 정렬해야 합니다. 그러면 SORT 단계가 추가되고 일치하는 주문 수가 증가함에 따라 비용이 더 많이 듭니다. 플래너를이 셰이프의 복합 인덱스로 제한하려면:

db.runCommand({planCacheSetFilter: "orders", query: { status: "SHIPPED" }, sort: { orderDate: 1 }, indexes: [ "status_1_orderDate_1" ]})

값은 셰이프에서 정규화되므로이 하나의 필터는 { status: "PENDING" }, { status: "CANCELLED" }및 동일한 정렬status로의 다른 모든 값도 포함합니다. 별도의 셰이프인 다른 정렬 또는 정렬 없는 동일한 조건자를 다루지 않습니다. 에서 필터가 적용되었는지 확인합니다explain.

db.orders.find({ status: "SHIPPED" }).sort({ orderDate: 1 }).explain()

출력은 indexFilterSet: true 및 indexFilterApplied: true를 보고하고 IXSCAN 단계 이름은 입니다status_1_orderDate_1.

예: 선택적 인덱스update에 고정

업데이트는 문서를 쓰기 전에 수정할 문서를 찾아야 하며, 해당 조회는 읽기와 동일한 방식으로 인덱스를 사용합니다. 조건자를 둘 이상의 인덱스에서 제공할 수 있는 경우 플래너가 선택한 인덱스에 따라 업데이트에서 검사하는 문서 수가 결정됩니다.

db.orders.updateMany( { customerId: 4815, status: "PENDING" }, { $set: { status: "CANCELLED" } } )

customerId_1 및 모두이 조건자를 제공할 status_1 수 있습니다. 업데이트를에 고정하려면customerId_1:

db.runCommand({planCacheSetFilter: "orders", query: { customerId: 4815, status: "PENDING" }, indexes: [ "customerId_1" ]})

쓰기 명령의 필터에는 Amazon DocumentDB 5.0.2 또는 8.0.2 및 플래너 버전 2.0 이상이 필요합니다. 업데이트explain의를 사용하여 확인합니다.

db.runCommand({explain: {update: "orders", updates: [{ q: { customerId: 4815, status: "PENDING" }, u: { $set: { status: "CANCELLED" } }, multi: true }]}})

이기는 계획은 IXSCAN의에 대한 UPDATE 단계입니다customerId_1. 셰이프에 쓰기 유형이 포함되지 않으므로이 쿼리 셰이프를 사용하는 delete 및 findAndModify 명령에는 동일한 필터가 적용됩니다.

예: aggregate 파이프라인 및 $lookup 외래 컬렉션 고정

집계의 경우 셰이프는 선행 $match 단계에서 가져온 다음 $sort 바로 뒤에를 만듭니다. $group 또는와 같은 그 이상의 스테이지$project는 셰이프의 일부가 아닙니다.

db.orders.aggregate([ { $match: { status: "SHIPPED" } }, { $group: { _id: "$customerId", total: { $sum: "$amount" } } } ])

$match 조건자에 설정된 필터는 orders를 읽는 데 사용되는 인덱스를 구동합니다.

db.runCommand({planCacheSetFilter: "orders", query: { status: "SHIPPED" }, indexes: [ "status_1" ]})

필터는 $lookup 또는 $graphLookup 단계가 조인하는 컬렉션에도 적용됩니다. 필터는 파이프라인이 실행되는 컬렉션이 아닌 외래 컬렉션에 설정됩니다. 다음 파이프라인에서 orders는 외부 컬렉션이고는 외부 컬렉션customers입니다.

db.orders.aggregate([ { $lookup: { from: "customers", localField: "customerId", foreignField: "customerId", as: "customer" } } ])

조인 프로브는 외부 문서당 customers 한 번씩 실행되므로 선택한 인덱스가 반복적으로 적용되고 파이프라인 전체에 비용이 곱해집니다. 해당 스캔을 특정 인덱스에 고정하려면 조인 키의 등식 셰이프에 customers 대해 필터를에 설정합니다.

db.runCommand({planCacheSetFilter: "customers", query: { customerId: 1 }, indexes: [ "customerId_1" ]})

값이 셰이프에서 정규화되므로 1 위의 값은 자리 표시자이며 모든 값은 동일한 필터를 생성합니다. 외래 수집 필터가 적용되면 최상위 indexFilterSet 및 indexFilterApplied 필드는 true를 보고하고, 선택한 필터가 낙찰 계획의 외래 측에 나타나는 인덱스를 보고합니다. 의 필터에는 Amazon DocumentDB 8.0.2 및 플래너 버전 3.0이 aggregate 필요합니다.

힌트 및 인덱스 변경 사항이 있는 동작

  • 계획 캐시 필터는 보다 우선합니다hint. Amazon DocumentDB는 먼저 필터를 적용한 다음 필터의 허용된 인덱스 목록 내에 힌트를 적용합니다. 힌트가 필터가 허용하는 인덱스의 이름을 지정하면 해당 인덱스가 사용됩니다. 힌트가 필터가 허용하지 않는 인덱스의 이름을 지정하는 경우 힌트는 무시되고 플래너는 허용되는 인덱스 중에서 비용을 기준으로 선택합니다. 두 힌트 형식 모두 인덱스 이름을 지정하든 키 패턴을 지정하든 동일한 방식으로 작동합니다.

    예를 들어 컬렉션에 인덱스 a_1_b_1, a_1 b_1및 foo가 있고 인덱스 목록 {query: {a: {$eq: "@"}, b: {$eq: "@"}}, sort: {a: 1}}를 사용하여 셰이프에 필터를 설정한 ["a_1", "a_1_b_1"]경우 a_1실행은 힌트에 이름이 지정되고 필터에서 허용되므로를 db.foo.find({ a: 10, b: 20 }).sort({a: 1}).hint({ a: 1 }) 사용합니다.

  • 인덱스를 삭제해도 필터는 수정되지 않습니다. 필터는 인덱스 이름을 유지합니다. 해당 인덱스가 누락된 동안 계획은 인덱스를 건너뜁니다. 필터 목록의 다른 인덱스가 쿼리를 처리할 수 있는 경우에도 필터는 계속 적용됩니다. 명명된 인덱스를 사용할 수 없는 경우에만가 indexFilterApplied 보고됩니다false. 동일한 이름의 인덱스를 다시 생성하면 다시 사용할 수 있습니다.

  • 컬렉션을 삭제하면 해당 컬렉션의 모든 필터가 제거됩니다.