View a markdown version of this page

Planificar filtros de caché - Amazon DocumentDB

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Planificar filtros de caché

Un filtro de caché del plan, también denominado filtro de índices, restringe el conjunto de índices que el planificador de consultas puede considerar para una forma de consulta específica. Cuando una consulta coincide con una forma que tiene un filtro, el planificador elige un plan solo entre los índices mencionados en ese filtro en lugar de evaluar todos los índices de la colección.

Una forma de consulta es la combinación del predicado de la consulta, la especificación de clasificación y el espacio de nombres de la colección, con los valores del predicado normalizados. Dos consultas que solo difieren en sus valores comparten una forma, por lo que un solo filtro las cubre todas. En la salida deplanCacheListFilters, los valores normalizados se muestran como"@".

Un filtro de caché del plan le permite fijar el plan para evitar elegir un índice más lento debido a la distribución de los datos o a los cambios en el índice. Los filtros tienen las siguientes propiedades:

  • No es necesario cambiar la aplicación. Los filtros se configuran con un comando de base de datos y se aplican en el servidor, por lo que puede mitigar una regresión sin necesidad de implementar código. Esta es la principal diferencia con respecto a ahint, que se debe agregar en cada sitio de llamada.

  • El ámbito es una forma de consulta. Una forma se define por la colección, el predicado y la clasificación, no por la consulta completa, por lo que un filtro restringe solo las consultas que coinciden con esa forma. Otras consultas de la misma colección se siguen planificando con normalidad.

  • El cambio es duradero. Los filtros persisten durante los reinicios de las instancias y los parches del motor. Al eliminar la colección, se eliminan sus filtros.

  • El cambio es reversible. Al borrar el filtro, se devuelve la forma a la planificación normal basada en los costos, por lo que un filtro es una forma de bajo riesgo de estabilizar una carga de trabajo mientras se investiga la causa subyacente.

Comandos admitidos

Los filtros de caché del plan requieren la versión 2.0 o posterior de Planner. El comando al que se puede aplicar un filtro depende de la versión del planificador y de la versión secundaria de Amazon DocumentDB, como se muestra en la tabla siguiente.

Soporte de comandos para los filtros de caché del plan
Comando Versión mínima del planificador Versión secundaria mínima

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

nota

La versión 3.0 de Planner solo está disponible en Amazon DocumentDB 8.0. Como los aggregate comandos distinct y requieren la versión 3.0 del planificador, los filtros de caché del plan para esos dos comandos solo están disponibles en Amazon DocumentDB 8.0. En Amazon DocumentDB 5.0, que admite la versión 2.0 del planificador, los filtros se aplican a los count comandos findupdate,delete, yfindAndModify.

Para el aggregate comando, la forma se toma desde la parte frontal de la canalización: la línea inicial $match proporciona el filtro e $sort inmediatamente después proporciona la clasificación. $skipy $limit no afectan a la forma, ni tampoco a las etapas que se encuentran más allá de ese punto.

Amazon DocumentDB optimiza la canalización antes de planificarla, y un filtro de caché del plan se compara con la canalización optimizada. Por lo tanto, el filtro y la clasificación que ve el planificador pueden diferir de las etapas que escribió. Por ejemplo, dos $match etapas adyacentes en la parte delantera de una canalización se combinan en un solo $and predicado:

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

El planificador ve uno $match activado{$and: [{status: ...}, {region: ...}]}, por lo que el filtro debe configurarse en ese predicado combinado.

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

Un filtro establecido en la colección extranjera de una $lookup o varias $graphLookup etapas controla el índice utilizado para escanear esa colección extranjera.

Formas de consulta compatibles

A partir de Amazon DocumentDB 5.0.2 y 8.0.2, los siguientes operadores pueden aparecer en forma de consulta con un filtro de caché de planes:

  • $text. La cadena de búsqueda está normalizada, por lo que las consultas que solo difieren en los términos que buscan comparten una forma.

  • $near y $nearSphere. Ambos operadores se normalizan con la misma forma. Las coordenadas $minDistance y no $maxDistance forman parte de la forma.

  • $geoWithin y $geoIntersects. El tipo de geometría GeoJSON forma parte de la forma, por lo que una Polygon consulta y una MultiPolygon consulta son formas diferentes. Las coordenadas no forman parte de la forma.

  • $regex, cuando se usa directamente en un campo. El patrón y las opciones están normalizados, por lo que todas las expresiones regulares del mismo campo comparten la misma forma.

La configuración de un filtro produce un error y se produce el código de error 303 para una forma de consulta que utilice $jsonSchema o$sampleRate. $expr También se produce un error en las siguientes formas. Una consulta que utilice cualquiera de ellas se planifica sin ningún filtro:

  • Un $regex anidado dentro de $in$nin, o$all. Una matriz que mezcla expresiones regulares con valores literales no se puede evaluar comparándola con un índice, por lo que nunca se podría aplicar un filtro a esa forma.

  • Una especie de especificación de{$natural: 1}. Una $natural clasificación solicita un escaneo de la colección, lo cual es incompatible con restringir el planificador a un índice.

Configurar, enumerar y borrar filtros

Para configurar un filtro de caché del plan, utilice el planCacheSetFilter comando. Los sort campos query y juntos especifican la forma de la consulta y indexes muestran los nombres de índice que el planificador puede tener en cuenta para esa forma.

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

Por ejemplo, el siguiente comando restringe el planificador al a_1 índice de la forma {a: {$eq: "@"}, b: {$eq: "@"}} sin ningún tipo de clasificación:

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

Al establecer un filtro para una forma que ya tiene uno, se reemplaza el filtro existente. Tras ejecutar los dos comandos siguientes, el filtro de la forma {a: {$eq: "@"}, b: {$eq: "@"}} es["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" ]})

Para mostrar todos los filtros de una colección, utilice el planCacheListFilters comando:

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

El resultado muestra cada forma almacenada con sus valores normalizados y su lista de índices permitidos:

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

El operador se conserva y solo se reemplaza el valor por. "@" Una igualdad implícita, tal como, {a: 1} aparece en su forma explícita{"a": {"$eq": "@"}}, y los elementos de una $in matriz se reemplazan como un todo, como{"a": {"$in": "@"}}. Un conjunto de filtros sin clasificación aparece junto con un sort documento vacío.

Para eliminar los filtros, utilice el planCacheClearFilters comando.

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

Para borrar todos los filtros de la colección, omite ambos query ysort:

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

Suministra ambos query y sort borra solo el filtro que tiene ese tipo exacto. Los valores introducidos query se normalizan, por lo que cualquier valor representativo funciona. Para borrar solo el filtro que se estableció sin ordenar, pase un sort documento vacío:

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

Comprobar que se ha aplicado un filtro

El explain resultado incluye dos campos que indican el estado del filtro de caché del plan:

  • indexFilterSetes true cuando existe un filtro en la colección para la forma de la consulta.

  • indexFilterAppliedes true solo cuando la consulta se planificó con un índice de la lista de ese filtro.

A partir de Amazon DocumentDB 5.0.2 y 8.0.2, estos campos se incluyen en todos los comandos que admiten los filtros de caché de planificación y en los resultados del generador de perfiles de esos comandos. En versiones secundarias anteriores, solo se indicaban para el comando. find Para obtener más información sobre la lectura y la explicación del resultado, consulteAnálisis del plan de consultas.

Un filtro puede coincidir con la forma de una consulta sin aplicarlo. Si ninguno de los índices de la lista del filtro sirve para la consulta, el planificador vuelve a planificar sin el filtro y elige un índice según el costo. En ese caso indexFilterSet es true y es. indexFilterApplied false Esto ocurre cuando los índices con nombre no cubren los campos de la consulta, cuando los índices con nombre no existen o cuando una $regex forma no puede generar límites de índice, como un patrón desanclado o que no distingue mayúsculas de minúsculas.

Ejemplos

En los siguientes ejemplos se utiliza una orders colección, y una customers colección, para el ejemplo, con estos índices: $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

Ejemplo: anclar una consulta de búsqueda a un índice compuesto

Imagínese una consulta que filtra status y ordena segúnorderDate:

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

El índice compuesto status_1_orderDate_1 satisface tanto el predicado como la clasificación, por lo que no es necesaria una clasificación por separado. Si el planificador lo eligestatus_1, la consulta tiene que ordenar sus resultados, lo que añade una SORT etapa y se encarece a medida que aumenta el número de pedidos coincidentes. Para restringir el planificador al índice compuesto de esta forma:

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

Como los valores se normalizan sin tener en cuenta la forma, este filtro también cubre { status: "PENDING" }{ status: "CANCELLED" }, y todos los demás valores de status la misma clasificación. No cubre el mismo predicado con un orden diferente o sin ningún tipo de clasificación, que son formas independientes. Confirme que el filtro se ha aplicado conexplain:

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

Los informes de salida indexFilterSet: true yindexFilterApplied: true, y los nombres de las IXSCAN etapasstatus_1_orderDate_1.

Ejemplo: fijar una actualización a un índice selectivo

Una actualización tiene que localizar los documentos que se van a modificar antes de poder escribirlos, y esa búsqueda utiliza un índice del mismo modo que lo hace una lectura. Cuando más de un índice puede servir de base a un predicado, el índice que elija el planificador determina cuántos documentos examina la actualización.

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

Ambos customerId_1 y status_1 pueden servir para este predicado. Para anclar la actualización acustomerId_1:

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

Los filtros de los comandos de escritura requieren Amazon DocumentDB 5.0.2 u 8.0.2 y la versión 2.0 o posterior del planificador. Compruébelo con una explain de las actualizaciones:

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

El plan ganador es UPDATE superar una IXSCAN etapacustomerId_1. Se aplica el mismo filtro a delete los findAndModify comandos que utilizan esta forma de consulta, ya que la forma no incluye el tipo de escritura.

Ejemplo: anclar una canalización agregada y una colección externa de $lookup

En el caso de una agregación, la forma se toma de la $match fase inicial e $sort inmediatamente después de ella. Las etapas posteriores, como $group o$project, no forman parte de la figura.

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

Un filtro establecido en el $match predicado controla el índice que se utiliza para leer: orders

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

Los filtros también se aplican a la colección a la que se une una $graphLookup etapa $lookup o. El filtro se establece en la colección externa, no en la colección con la que se ejecuta la canalización. En la siguiente canalización, orders está la colección externa y customers es la colección externa:

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

Los sondeos se unen customers una vez por documento externo, por lo que el índice elegido allí se aplica repetidamente y su coste se multiplica por todo el proceso. Para fijar ese escaneo a un índice específico, active el filtro customers para la forma de igualdad de la clave de unión:

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

Dado que los valores se normalizan fuera de la forma, el valor 1 anterior es un marcador de posición y cualquier valor produce el mismo filtro. Cuando se aplica un filtro de recopilación extranjera, aparecen el nivel superior y los indexFilterApplied campos, indexFilterSet y el índice en true el que se basa el filtro seleccionado aparece en la parte externa del plan ganador. Los filtros activados aggregate requieren Amazon DocumentDB 8.0.2 y Planner versión 3.0.

Comportamiento con sugerencias y cambios en el índice

  • Un filtro de caché del plan tiene prioridad sobre unhint. Amazon DocumentDB aplica primero el filtro y, a continuación, aplica la sugerencia dentro de la lista de índices permitidos del filtro. Si la sugerencia nombra un índice permitido por el filtro, se utiliza ese índice. Si la sugerencia nombra un índice que el filtro no permite, la sugerencia se ignora y el planificador elige entre los índices permitidos en función del costo. Ambas formas de sugerencia se comportan de la misma manera, tanto si se asigna un nombre al índice como si se indica su patrón clave.

    Por ejemplo, si la colección foo contiene los índicesa_1, y b_1a_1_b_1, y se establece un filtro en la forma {query: {a: {$eq: "@"}, b: {$eq: "@"}}, sort: {a: 1}} con la lista de índices["a_1", "a_1_b_1"], se db.foo.find({ a: 10, b: 20 }).sort({a: 1}).hint({ a: 1 }) utiliza la ejecucióna_1, ya que aparece en la sugerencia y el filtro lo permite.

  • Eliminar un índice no modifica los filtros. El filtro conserva el nombre del índice. Mientras falta ese índice, la planificación lo omite. Si otro índice de la lista del filtro puede servir para la consulta, el filtro seguirá aplicándose. El indexFilterApplied informe false solo se publica cuando ninguno de los índices con nombre está disponible. Al volver a crear un índice con el mismo nombre, vuelve a ser elegible.

  • Al eliminar una colección, se eliminan todos los filtros de esa colección.