View a markdown version of this page

Cache-Filter planen - Amazon DocumentDB

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Cache-Filter planen

Ein Plan-Cache-Filter, auch Indexfilter genannt, schränkt die Menge der Indizes ein, die der Abfrageplaner für eine bestimmte Abfrageform berücksichtigen darf. Wenn eine Abfrage mit einem Shape übereinstimmt, das über einen Filter verfügt, wählt der Planer einen Plan nur aus den in diesem Filter genannten Indizes aus, anstatt jeden Index in der Sammlung auszuwerten.

Ein Abfrage-Shape ist die Kombination aus dem Abfrageprädikat, der Sortierspezifikation und dem Sammlungsnamespace, wobei die Prädikatwerte normalisiert sind. Zwei Abfragen, die sich nur in ihren Werten unterscheiden, haben eine gemeinsame Form, sodass ein einziger Filter sie alle abdeckt. In der Ausgabe von planCacheListFilters werden normalisierte Werte als "@" angezeigt.

Mit einem Plan-Cache-Filter können Sie den Plan fixieren, sodass Sie vermeiden müssen, aufgrund der Datenverteilung oder Indexänderungen einen langsameren Index auszuwählen. Filter haben die folgenden Eigenschaften:

  • Es ist keine Änderung der Anwendung erforderlich. Filter werden mit einem Datenbankbefehl festgelegt und auf dem Server angewendet, sodass Sie eine Regression ohne Codebereitstellung abschwächen können. Dies ist der Hauptunterschied zu einemhint, das an jeder Anrufstelle hinzugefügt werden muss.

  • Der Gültigkeitsbereich ist ein Abfrage-Shape. Eine Form wird durch die Sammlung, das Prädikat und die Sortierung definiert, nicht durch die vollständige Abfrage, sodass ein Filter nur die Abfragen einschränkt, die dieser Form entsprechen. Andere Abfragen in derselben Sammlung werden weiterhin normal geplant.

  • Die Änderung ist dauerhaft. Filter bleiben auch bei Instanzneustarts und Engine-Patches bestehen. Wenn Sie die Sammlung löschen, werden ihre Filter entfernt.

  • Die Änderung ist reversibel. Wenn Sie den Filter löschen, kehrt die Form zur normalen kostenbasierten Planung zurück. Ein Filter ist also eine risikoarme Methode, um eine Arbeitslast zu stabilisieren, während Sie die zugrunde liegende Ursache untersuchen.

Unterstützte Befehle

Für Plan-Cache-Filter ist Planner-Version 2.0 oder höher erforderlich. Der Befehl, auf den ein Filter angewendet werden kann, hängt von der Planner-Version und der Amazon DocumentDB-Nebenversion ab, wie in der folgenden Tabelle dargestellt.

Befehlsunterstützung für Plan-Cache-Filter
Befehl Minimale Planerversion Minimale Nebenversion

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

Anmerkung

Planner Version 3.0 ist nur in Amazon DocumentDB 8.0 verfügbar. Da für die aggregate Befehle distinct und die Planner-Version 3.0 erforderlich ist, sind Plan-Cache-Filter für diese beiden Befehle nur in Amazon DocumentDB 8.0 verfügbar. In Amazon DocumentDB 5.0, das Planner-Version 2.0 unterstützt, gelten Filter für die count Befehlefind, updatedelete, undfindAndModify.

Für den aggregate Befehl wird die Form von der Vorderseite der Pipeline übernommen: Die erste Seite $match versorgt den Filter und eine $sort unmittelbar danach liegende Leitung versorgt die Sortierung. $skipund wirken sich $limit nicht auf die Form aus, ebenso wenig wie die Stufen hinter diesem Punkt.

Amazon DocumentDB optimiert die Pipeline vor der Planung, und ein Plan-Cache-Filter wird mit der optimierten Pipeline abgeglichen. Der Filter und die Sortierung, die der Planer sieht, können sich daher von den Phasen unterscheiden, die Sie geschrieben haben. Beispielsweise werden zwei benachbarte $match Stufen an der Vorderseite einer Pipeline zu einem einzigen $and Prädikat zusammengefasst:

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

Der Planer sieht ein $match {$and: [{status: ...}, {region: ...}]} Prädikat aktiviert, daher muss der Filter auf dieses kombinierte Prädikat gesetzt werden.

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

Ein Filter, der für die ausländische Sammlung einer $lookup $graphLookup OR-Stufe gesetzt wird, steuert den Index, der zum Scannen dieser fremden Sammlung verwendet wird.

Unterstützte Abfrage-Shapes

Ab Amazon DocumentDB 5.0.2 und 8.0.2 können die folgenden Operatoren in einem Abfrage-Shape erscheinen, das über einen Plan-Cache-Filter verfügt:

  • $text. Die Suchzeichenfolge ist normalisiert, sodass Abfragen, die sich nur in den Begriffen unterscheiden, nach denen sie suchen, eine gemeinsame Form haben.

  • $near und $nearSphere. Beide Operatoren normalisieren sich auf dieselbe Form. Die Koordinaten$minDistance, und $maxDistance sind nicht Teil der Form.

  • $geoWithin und $geoIntersects. Der GeoJSON-Geometrietyp ist Teil der Form, sodass eine Polygon Abfrage und eine MultiPolygon Abfrage unterschiedliche Formen haben. Die Koordinaten sind nicht Teil der Form.

  • $regex, wenn es direkt auf einem Feld verwendet wird. Das Muster und die Optionen sind normalisiert, sodass alle regulären Ausdrücke im gleichen Feld dieselbe Form haben.

Das Setzen eines Filters schlägt mit dem Fehlercode 303 für ein Abfrage-Shape fehl, das $jsonSchema$expr, oder $sampleRate verwendet. Es schlägt auch bei den folgenden Formen fehl. Eine Abfrage, die einen von ihnen verwendet, ist ohne Filter geplant:

  • Ein darin $regex verschachteltes $in$nin, oder$all. Ein Array, das reguläre Ausdrücke mit Literalwerten mischt, kann nicht anhand eines Indexes ausgewertet werden. Daher könnte niemals ein Filter auf diese Form angewendet werden.

  • Eine Art Spezifikation von. {$natural: 1} Eine $natural Sortierung fordert einen Sammlungsscan an, was mit der Beschränkung des Planers auf einen Index nicht vereinbar ist.

Filter setzen, auflisten und löschen

Verwenden Sie den planCacheSetFilter Befehl, um einen Plan-Cache-Filter einzurichten. Die sort Felder query und geben zusammen das Abfrage-Shape an und indexes listen die Indexnamen auf, die der Planer für dieses Shape berücksichtigen darf.

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

Beispielsweise beschränkt der folgende Befehl den Planer auf den a_1 Index für die Form {a: {$eq: "@"}, b: {$eq: "@"}} ohne Sortierung:

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

Wenn Sie einen Filter für eine Form festlegen, für die bereits ein Filter vorhanden ist, wird der vorhandene Filter ersetzt. Nachdem Sie die folgenden beiden Befehle ausgeführt haben, {a: {$eq: "@"}, b: {$eq: "@"}} lautet der Filter für die Form["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" ]})

Verwenden Sie den planCacheListFilters folgenden Befehl, um alle Filter einer Sammlung aufzulisten:

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

Die Ausgabe zeigt jede gespeicherte Form mit ihren normalisierten Werten und der Liste der zulässigen Indizes:

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

Der Operator wird beibehalten und nur der Wert wird durch ersetzt"@". Eine implizite Gleichheit wie {a: 1} wird in ihrer expliziten Form aufgeführt{"a": {"$eq": "@"}}, und die Elemente eines $in Arrays werden als Ganzes ersetzt, als{"a": {"$in": "@"}}. Ein Filtersatz ohne Sortierung wird mit einem leeren sort Dokument aufgeführt.

Verwenden Sie den planCacheClearFilters Befehl, um Filter zu entfernen.

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

Um alle Filter in der Sammlung zu löschen, lassen Sie beide weg query undsort:

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

Wenn Sie beide query angeben, sort wird nur der Filter gelöscht, der genau diese Sortierung hat. Die Werte in query sind normalisiert, sodass jeder repräsentative Wert funktioniert. Um nur den Filter zu löschen, der ohne Sortierung gesetzt wurde, übergeben Sie ein leeres sort Dokument:

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

Stellen Sie sicher, dass ein Filter angewendet wird

Die explain Ausgabe enthält zwei Felder, die den Status des Plan-Cache-Filters melden:

  • indexFilterSetliegt vortrue, wenn in der Sammlung ein Filter für die Form der Abfrage vorhanden ist.

  • indexFilterAppliedist true nur dann der Fall, wenn die Abfrage anhand eines Indexes aus der Liste dieses Filters geplant wurde.

Ab Amazon DocumentDB 5.0.2 und 8.0.2 werden diese Felder für jeden Befehl gemeldet, der Plan-Cache-Filter unterstützt, und in der Profiler-Ausgabe für diese Befehle. In früheren Nebenversionen wurden sie nur für den Befehl gemeldet. find Weitere Hinweise zum Lesen der Explain-Ausgabe finden Sie unterPlananalyse abfragen.

Ein Filter kann einer Abfrageform entsprechen, ohne angewendet zu werden. Wenn keiner der Indizes in der Liste des Filters die Abfrage verarbeiten kann, plant der Planer ohne den Filter neu und wählt einen Kostenindex aus. In diesem Fall indexFilterSet ist true und indexFilterApplied ist. false Dies passiert, wenn die benannten Indizes die Felder der Abfrage nicht abdecken, wenn die benannten Indizes nicht existieren oder wenn eine $regex Form keine Indexgrenzen erzeugen kann, z. B. ein Muster ohne Verankerung oder ohne Berücksichtigung der Groß- und Kleinschreibung.

Beispiele

In den folgenden Beispielen wird eine orders Sammlung und für das Beispiel eine customers Sammlung mit diesen Indizes verwendet: $lookup

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

Beispiel: Eine Suchabfrage an einen zusammengesetzten Index anheften

Stellen Sie sich eine Abfrage vor, die nach folgenden status Kriterien filtert und sortiert: orderDate

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

Der zusammengesetzte Index status_1_orderDate_1 erfüllt sowohl das Prädikat als auch die Sortierung, sodass keine separate Sortierung erforderlich ist. Wählt der Planer stattdessenstatus_1, muss die Abfrage ihre Ergebnisse sortieren, wodurch eine weitere SORT Stufe hinzugefügt wird und mit zunehmender Anzahl übereinstimmender Bestellungen teurer wird. Um den Planer auf den zusammengesetzten Index für diese Form zu beschränken:

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

Da Werte außerhalb der Form normalisiert werden { status: "PENDING" }{ status: "CANCELLED" }, deckt dieser Filter auch alle anderen Werte von status mit derselben Sortierung ab. Er deckt nicht dasselbe Prädikat mit einer anderen Sortierung oder ohne Sortierung ab, bei denen es sich um separate Formen handelt. Bestätigen Sie das Wirksamwerden des Filters mitexplain:

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

Die Ausgabe meldet indexFilterSet: true undindexFilterApplied: true, und die IXSCAN Etappennamenstatus_1_orderDate_1.

Beispiel: Ein Update an einen selektiven Index anheften

Bei einer Aktualisierung müssen die zu ändernden Dokumente gefunden werden, bevor sie geschrieben werden können. Diese Suche verwendet einen Index auf die gleiche Weise wie ein Lesevorgang. Wenn ein Prädikat von mehr als einem Index bereitgestellt werden kann, bestimmt der vom Planer gewählte Index, wie viele Dokumente bei der Aktualisierung untersucht werden.

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

Beides customerId_1 und status_1 kann dieses Prädikat erfüllen. Um das Update anzuheften ancustomerId_1:

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

Filter für Schreibbefehle erfordern Amazon DocumentDB 5.0.2 oder 8.0.2 und Planner Version 2.0 oder höher. Überprüfen Sie mit einem explain der Updates:

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

Der Plan, der den Sieg davonträgt, ist eine UPDATE Stufe höher als IXSCAN die anderecustomerId_1. Derselbe Filter gilt für findAndModify Befehle delete und Befehle, die dieses Abfrage-Shape verwenden, da das Shape den Typ des Schreibens nicht enthält.

Beispiel: Anheften einer Aggregatpipeline und einer $lookup-Fremdsammlung

Bei einer Aggregation wird die Form aus der ersten $match Phase und einer $sort unmittelbar darauf folgenden Phase übernommen. Stufen, die darüber hinausgehen, wie z. B. $group oder$project, sind nicht Teil der Form.

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

Ein auf das $match Prädikat gesetzter Filter steuert den Index, der zum Lesen orders verwendet wird:

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

Filter gelten auch für die Sammlung, zu der eine $lookup oder $graphLookup -Stufe gehört. Der Filter wird für die fremde Sammlung gesetzt, nicht für die Sammlung, gegen die die Pipeline läuft. In der folgenden Pipeline orders befindet sich die äußere Sammlung und customers ist die ausländische Sammlung:

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

Der Join wird customers einmal pro äußerem Dokument geprüft, sodass der dort gewählte Index wiederholt angewendet wird und die damit verbundenen Kosten in der gesamten Pipeline multipliziert werden. Um diesen Scan einem bestimmten Index zuzuordnen, aktivieren Sie den Filter customers für die Gleichheitsform des Join-Schlüssels:

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

Da Werte außerhalb der Form normalisiert werden, ist der 1 obige Wert ein Platzhalter, und jeder Wert erzeugt denselben Filter. Wenn ein Filter für ausländische Sammlungen angewendet wird, werden die oberste Ebene indexFilterSet und die indexFilterApplied Felder gemeldet, und der Indextrue, für den der Filter ausgewählt wurde, wird auf der Fremdseite des Gewinnerplans angezeigt. Für aktivierte Filter aggregate sind Amazon DocumentDB 8.0.2 und Planner Version 3.0 erforderlich.

Verhalten bei Hinweisen und Indexänderungen

  • Ein Plan-Cache-Filter hat Vorrang vor einemhint. Amazon DocumentDB wendet zuerst den Filter an und wendet dann den Hinweis in der Liste der zulässigen Indizes des Filters an. Wenn der Hinweis einen Index benennt, den der Filter zulässt, wird dieser Index verwendet. Wenn der Hinweis einen Index benennt, den der Filter nicht zulässt, wird der Hinweis ignoriert und der Planer wählt einen der zulässigen Indizes nach den Kosten aus. Beide Hinweisformen verhalten sich gleich, unabhängig davon, ob Sie den Index benennen oder sein Schlüsselmuster angeben.

    Wenn die Sammlung beispielsweise die Indizesa_1, b_1a_1_b_1, und foo hat und Sie einen Filter auf die Form {query: {a: {$eq: "@"}, b: {$eq: "@"}}, sort: {a: 1}} mit der Indexliste setzen["a_1", "a_1_b_1"], wird das Ausführen db.foo.find({ a: 10, b: 20 }).sort({a: 1}).hint({ a: 1 }) verwendeta_1, da es im Hinweis benannt ist und vom Filter zugelassen wird.

  • Durch das Löschen eines Indexes werden die Filter nicht geändert. Der Filter behält den Indexnamen bei. Obwohl dieser Index fehlt, wird er von der Planung übersprungen. Wenn ein anderer Index in der Liste des Filters die Abfrage verarbeiten kann, gilt der Filter trotzdem. Nur wenn keiner der benannten Indizes verfügbar ist, wird ein indexFilterApplied Bericht erstelltfalse. Wenn Sie einen Index mit demselben Namen neu erstellen, ist er wieder gültig.

  • Wenn Sie eine Sammlung löschen, werden alle Filter dieser Sammlung entfernt.