Directivas de indexación en Azure Cosmos DB
SE APLICA A: NoSQL
En Azure Cosmos DB, cada contenedor tiene una directiva de indexación que determina cómo se deben indexar los elementos del contenedor. La directiva de indexación predeterminada para los contenedores recién creados indexa cada propiedad de cada elemento y exige que se usen índices de intervalo para todas las cadenas o números. Esto permite obtener un buen rendimiento de las consultas sin tener que pensar en la indexación ni en la administración de índices por adelantado.
En algunas situaciones, puede que quiera invalidar este comportamiento automático para ajustarse mejor a sus requisitos. Puede personalizar la directiva de indexación de un contenedor estableciendo su modo de indexación e incluir o excluir las rutas de acceso de propiedad.
Nota:
El método de actualización de las directivas de indexación que se describe en este artículo solo se aplica a la API de Azure Cosmos DB para NoSQL. Obtenga más información sobre la indexación en la API de Azure Cosmos DB para MongoDB
Modo de indexación
Azure Cosmos DB admite dos modos de indexación:
- Coherente: El índice se actualiza de forma sincrónica al crear, actualizar o eliminar elementos. Esto significa que la coherencia de las consultas de lectura será la coherencia configurada para la cuenta.
- Ninguna: La indexación está deshabilitada en el contenedor. Este modo se utiliza normalmente cuando se usa un contenedor como un almacén de pares clave-valor puro sin necesidad de índices secundarios. También se puede usar para mejorar el rendimiento de las operaciones masivas. Una vez completadas las operaciones masivas, el modo de índice se puede establecer en Coherente y supervisarse mediante IndexTransformationProgress hasta que se complete.
Nota:
Azure Cosmos DB también admite un modo de indexación diferida. La indexación diferida realiza actualizaciones en el índice con un nivel de prioridad mucho menor cuando el motor no realiza ningún otro trabajo. Esto puede producir resultados de consulta incoherentes o incompletos. Si tiene previsto consultar un contenedor de Azure Cosmos DB, no debe seleccionar la indexación diferida. Los nuevos contenedores no pueden seleccionar la indexación diferida. Puede ponerse en contacto con el cosmosdbindexing@microsoft.com para solicitar una exención (excepto si usa una cuenta de Azure Cosmos DB en modo sin servidor, que no admite la indexación diferida).
De forma predeterminada, la directiva de indexación se establece en automatic
. Esto se consigue al establecer la propiedad automatic
de la directiva de indexación en true
. Al establecer esta propiedad en true
, se permite que Azure Cosmos DB indexe automáticamente los artículos a medida que se escriben.
Tamaño de índice
En Azure Cosmos DB, el almacenamiento total consumido es la combinación del tamaño de los datos y del tamaño del índice. A continuación se muestran algunas características del tamaño del índice:
- El tamaño del índice depende de la directiva de indexación. Si todas las propiedades están indexadas, el tamaño del índice puede ser mayor que el tamaño de los datos.
- Cuando se eliminan datos, los índices se compactan de manera casi continua. Sin embargo, en el caso de pequeñas eliminaciones de datos, es posible que no se observe inmediatamente una disminución en el tamaño del índice.
- El tamaño del índice puede aumentar temporalmente cuando se dividen las particiones físicas. El espacio del índice se libera una vez completada la división de particiones.
Inclusión y exclusión de rutas de acceso de propiedad
Una directiva de indexación personalizada puede especificar rutas de acceso de propiedad que se incluyen o excluyen de forma explícita de la indexación. Al optimizar el número de rutas de acceso que están indexadas, puede reducir considerablemente la latencia y el cargo de RU de las operaciones de escritura. Estas rutas de acceso se definen siguiendo el método descrito en la sección de introducción a la indexación, con las siguientes adiciones:
- Una ruta de acceso que lleva a un valor escalar (cadena o número) termina con
/?
. - Los elementos de una matriz se dirigen juntos a través de la notación
/[]
(en lugar de/0
,/1
etcétera). - El carácter comodín
/*
puede utilizarse para que coincida con cualquier elemento debajo del nodo.
Tomando el mismo ejemplo de nuevo:
{
"locations": [
{ "country": "Germany", "city": "Berlin" },
{ "country": "France", "city": "Paris" }
],
"headquarters": { "country": "Belgium", "employees": 250 },
"exports": [
{ "city": "Moscow" },
{ "city": "Athens" }
]
}
La ruta de acceso
employees
deheadquarters
es/headquarters/employees/?
.La ruta de acceso
country
delocations
es/locations/[]/country/?
.La ruta de acceso de todo lo que incluye
headquarters
es/headquarters/*
.
Por ejemplo, podríamos incluir la ruta de acceso /headquarters/employees/?
. Esta ruta de acceso garantiza que indexamos la propiedad employees
, pero no se indexará ningún archivo JSON anidado adicional en esta propiedad.
Inclusión o exclusión de estrategia
Cualquier directiva de indexación tiene que incluir la ruta de acceso raíz /*
así como una ruta de acceso incluida o una excluida.
Incluya la ruta de acceso raíz para excluir selectivamente las rutas de acceso que no se deban indexar. Este enfoque se recomienda, ya que permite a Azure Cosmos DB indexar de forma proactiva las propiedades nuevas que se pueden agregar a su modelo.
Excluya la ruta de acceso raíz para incluir selectivamente las rutas de acceso que se deban indexar. La ruta de acceso de la propiedad de clave de partición no se indexa de forma predeterminada con la estrategia de exclusión y debe incluirse explícitamente si es necesario.
Para las rutas de acceso con caracteres normales que incluyen: caracteres alfanuméricos y _ (guion bajo), no tiene que aplicar el escape a la cadena de ruta de acceso en comillas dobles (por ejemplo, "/path/?"). Para las rutas de acceso con otros caracteres especiales, necesitará aplicar el escape a la cadena de ruta de acceso en comillas dobles (por ejemplo, "/"path-abc"/?"). Si se esperan caracteres especiales en la ruta de acceso, puede aplicar el escape a las rutas de acceso por motivos de seguridad. Funcionalmente, no hay ninguna diferencia si aplica el escape a todas las rutas de acceso o lo aplica solo a las que tienen caracteres especiales.
De forma predeterminada, la propiedad del sistema
_etag
se excluye de la indexación, a menos que la ETag se agregue a la ruta de acceso incluida para la indexación.Si el modo de indexación se establece en Coherente, las propiedades del sistema
id
y_ts
se indexan automáticamente.Si una ruta de acceso indizada explícitamente no existe en un elemento, se agregará un valor al índice para indicar que la ruta de acceso no está definida.
Todas las rutas de acceso incluidas explícitamente tienen valores agregados al índice para cada elemento del contenedor, incluso si la ruta de acceso no está definida para un elemento determinado.
Consulte esta sección para obtener ejemplos de directivas de indexación a fin de incluir y excluir rutas de acceso.
Precedencia de inclusión o exclusión
Si las rutas de acceso incluidas y las rutas de acceso excluidas tienen un conflicto, la ruta de acceso más precisa tiene prioridad.
Este es un ejemplo:
Ruta de acceso incluida: /food/ingredients/nutrition/*
Ruta de acceso excluida: /food/ingredients/*
En este caso, la ruta de acceso incluida tiene prioridad sobre la ruta de acceso excluida porque es más precisa. En función de estas rutas de acceso, los datos de la ruta de acceso food/ingredients
o anidados dentro de ella se excluirán del índice. La excepción serían los datos dentro de la ruta de acceso incluida: /food/ingredients/nutrition/*
, que se indexaría.
Estas son algunas reglas para la prioridad de las rutas de acceso incluidas y excluidas en Azure Cosmos DB:
Las rutas de acceso más profundas son más precisas que las rutas más estrechas. Por ejemplo:
/a/b/?
es más preciso que/a/?
./?
es más preciso que/*
. Por ejemplo,/a/?
es más preciso que/a/*
, por lo que/a/?
tiene prioridad.La ruta de acceso
/*
debe ser una ruta de acceso incluida o una ruta de acceso excluida.
Índices de texto completo
Nota:
Debe habilitar la característica en vista previa (GB)Full Text & Hybrid Search for NoSQL API para especificar un índice de texto completo.
Los índices de Texto completo permiten la búsqueda de texto completo y la puntuación de forma eficaz mediante el índice. La definición de una ruta de acceso de texto completo en una directiva de indexación se puede realizar fácilmente mediante la inclusión de una sección fullTextIndexes
de la directiva de indexación que contiene todas las rutas de acceso de texto que se van a indexar. Por ejemplo:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/\"_etag\"/?"
},
],
"fullTextIndexes": [
{
"path": "/text"
}
]
}
Importante
Una directiva de indexación de texto completo debe estar en la ruta de acceso definida en la directiva de texto completo del contenedor. Más información sobre las directivas de vectores de contenedor.
Índices vectoriales
Nota:
Debe habilitar la Característica del vector de búsqueda de Azure Cosmos DB NoSQL para especificar un índice vectorial.
Los índices vectoriales aumentan la eficacia al realizar búsquedas vectoriales mediante la función del sistema VectorDistance
. Las búsquedas de vectores tienen menor latencia, mayor rendimiento y menor consumo de RU cuando se usa un índice vectorial. Puede especificar los siguientes tipos de directivas de índice vectorial:
Tipo | Descripción | Dimensiones máximas |
---|---|---|
flat |
Almacena vectores en el mismo índice que otras propiedades indexadas. | 505 |
quantizedFlat |
Cuantifica (comprime) vectores antes de almacenarlos en el índice. Esto puede mejorar la latencia y el rendimiento a costa de una pequeña cantidad de precisión. | 4096 |
diskANN |
Crea un índice basado en DiskANN para una búsqueda aproximada rápida y eficaz. | 4096 |
Importante
Actualmente, las directivas de vectores y los índices vectoriales son inmutables después de la creación. Para realizar cambios, cree una nueva colección.
Algunos puntos a tener en cuenta:
Los tipos de índice
flat
yquantizedFlat
aplican el índice de Azure Cosmos DB para almacenar y leer cada vector al realizar una búsqueda de vectores. Las búsquedas vectoriales con un índice deflat
son búsquedas por fuerza bruta y producen una precisión o recuperación del 100 %. Es decir, se garantiza que se encuentren los vectores más similares en el conjunto de datos. Sin embargo, hay una limitación de505
dimensiones para vectores en un índice plano.El índice
quantizedFlat
almacena vectores cuantificados (comprimidos) en el índice. El vector de búsqueda conquantizedFlat
índice también son búsquedas por fuerza bruta, pero su precisión podría ser ligeramente inferior al 100 %, ya que los vectores se cuantifican antes de agregar al índice. Sin embargo, las búsquedas vectoriales conquantized flat
deben tener una latencia menor, un mayor rendimiento y un menor costo de RU que el vector de búsqueda en un índiceflat
. Esta es una buena opción para escenarios en los que se usan filtros de consulta para restringir la búsqueda de vectores a un conjunto relativamente pequeño de vectores y se requiere una precisión elevada.El índice
diskANN
es un índice independiente definido específicamente para vectores que aplican DiskANN, un conjunto de algoritmos de indexación de vectores de alto rendimiento desarrollados por Microsoft Research. Los índices diskANN pueden ofrecer algunas de las consultas de menor latencia, mayor rendimiento y costo de RU más bajo, a la vez que mantienen una alta precisión. Sin embargo, dado que DiskANN es un índice aproximado de vecinos más cercanos (ANN), la precisión puede ser menor quequantizedFlat
oflat
.
Los índices diskANN
y quantizedFlat
pueden tomar parámetros de compilación de índices opcionales que se pueden usar para ajustar la precisión frente a la desventaja de latencia que se aplica a cada índice de vectores vecinos más próximo aproximado.
quantizationByteSize
: establece el tamaño (en bytes) para la cuantificación del producto. Mínimo=1, Valor predeterminado=dinámico (lo decide el sistema), Máximo=512. Establecer este valor de forma superior puede dar lugar a vectores de búsquedas de mayor precisión en base a un mayor costo de RU y una mayor latencia. Esto se aplica a los tipos de índicequantizedFlat
yDiskANN
.indexingSearchListSize
: establece cuántos vectores se van a buscar durante la construcción de la compilación del índice. Mínimo=10, Valor predeterminado=100, Máximo=500. Establecer este valor de forma superior puede dar lugar a vectores de búsquedas de mayor precisión en base a tiempos de compilación de índices más largos y latencias de ingesta de vectores más altas. Esto solo se aplica a los índices deDiskANN
.
Este es un ejemplo de una directiva de indexación con un índice vectorial:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/_etag/?",
},
{
"path": "/vector/*"
}
],
"vectorIndexes": [
{
"path": "/vector",
"type": "diskANN"
}
]
}
Importante
Una directiva de indexación de vectores debe estar en la ruta de acceso definida en la directiva de vectores del contenedor. Más información sobre las directivas de vectores de contenedor.
Importante
Ruta de acceso vectorial agregada a la sección "excludedPaths" de la directiva de indexación para garantizar un rendimiento optimizado para la inserción. Si no se agrega la ruta de acceso vectorial a "excludedPaths", se producirá una mayor carga de RU y latencia para las inserciones vectoriales.
Índices espaciales
Al definir una ruta de acceso espacial en la directiva de indexación, debe definir qué índice type
se debe aplicar a esa ruta de acceso. Los tipos posibles para los índices espaciales son:
Punto
Polygon
MultiPolygon
LineString
De forma predeterminada, Azure Cosmos DB no creará ningún índice espacial. Si quiere usar funciones integradas de SQL espaciales, debe crear un índice espacial en las propiedades necesarias. Consulte esta sección para obtener ejemplos de directivas de indexación sobre la adición de índices espaciales.
Índices de tupla
Los índices de tupla son útiles al realizar el filtrado en varios campos dentro de un elemento de matriz. Los índices de tupla se definen en la sección includedPaths de la directiva de indexación mediante el especificador de tupla "[]".
Nota:
A diferencia de las rutas de acceso incluidas o excluidas, no se puede crear una ruta de acceso con el carácter comodín /*. Cada ruta de tupla debe terminar con "/?". Si una tupla en una ruta de acceso de tupla no existe en un elemento, se agregará un valor al índice para indicar que la tupla no está definida.
Las rutas de tupla de matriz se definirán en la sección includedPaths y usarán la notación siguiente.
<path prefix>/[]/{<tuple 1>, <tuple 2> … <tuple n>}/?
Observe lo siguiente:
- La primera parte, el prefijo de ruta de acceso, es la ruta de acceso común entre las tuplas. Es la ruta de acceso de raíz a matriz. En nuestro ejemplo, es "/events".
- A continuación, se muestra el especificador de caracteres comodín de matriz "[]". Todas las rutas de tupla de matriz deben tener un especificador de caracteres comodín de matriz antes del especificador de tupla "{}".
- A continuación, se especifican las tuplas mediante el especificador de tupla "{}".
- Las tuplas se separarán por coma.
- La tupla debe usar la misma especificación de ruta de acceso que otras rutas de acceso de índice con algunas excepciones:
- Las tuplas no deben comenzar con la "/" inicial.
- Las tuplas no deben tener caracteres comodín de matriz.
- Las tuplas no deben terminar "?" o “*”
- “?” es el último segmento de una ruta de acceso de tupla y debe especificarse inmediatamente después del segmento del especificador de tupla.
Por ejemplo,
/events/[]/{name, category}/?
Estos son algunos ejemplos de rutas de tupla de matriz válidas :
“includedPaths”:[
{“path”: “/events/[]/{name/first, name/last}/?”},
{“path”: “/events/[]/{name/first, category}/?”},
{“path”: “/events/[]/{name/first, category/subcategory}/?”},
{“path”: “/events/[]/{name/[1]/first, category}/?”},
{“path”: “/events/[]/{[1], [3]}/?”},
{“path”: “/city/[1]/events/[]/{name, category}/?”}
]
Estos son algunos ejemplos de rutas de tupla de matriz no válidas
/events/[]/{name/[]/first, category}/?
- Una de las tuplas tiene comodín de matriz
/events/[]/{name, category}/*
- El último segmento de la ruta de acceso de tupla de matriz debe ser "?" y no *
/events/[]/{{name, first},category}/?
- El especificador de tupla está anidado
/events/{name, category}/?
- Falta el carácter comodín de matriz antes del especificador de tupla.
/events/[]/{/name,/category}/?
- Las tuplas comienzan con la punta
/
- Las tuplas comienzan con la punta
/events/[]/{name/?,category/?}/?
- Las tuplas terminan con un
?
- Las tuplas terminan con un
/city/[]/events/[]/{name, category}/?
- Prefijo de ruta de acceso como 2 caracteres comodín de matriz
Índices compuestos
Las consultas que tienen una cláusula ORDER BY
con dos o más propiedades requieren un índice compuesto. También puede definir un índice compuesto para mejorar el rendimiento de muchas consultas de igualdad y de intervalo. De forma predeterminada, no hay índices compuestos definidos, por lo que debe agregar índices compuestos según sea necesario.
A diferencia de las rutas de acceso incluidas o excluidas, no se puede crear una ruta de acceso con el carácter comodín /*
. Cada ruta de acceso compuesta tiene un carácter /?
implícito al final de la ruta de acceso que no es necesario especificar. Las rutas de acceso compuestas conducen a un valor escalar que es el único valor que se incluye en el índice compuesto. Si una ruta de acceso de un índice compuesto no existe en un elemento o lleva a un valor no escalar, se agrega un valor al índice para indicar que la ruta de acceso no está definida.
Al definir un índice compuesto, especifique lo siguiente:
Dos o más rutas de acceso de propiedad. La secuencia en la que se definen las rutas de acceso de propiedad importa.
El orden (ascendente o descendente).
Nota:
Al agregar un índice compuesto, la consulta utilizará los índices de intervalo existentes hasta que se complete la nueva adición de índice compuesto. Por lo tanto, al agregar un índice compuesto, es posible que no observe inmediatamente las mejoras en el rendimiento. Es posible realizar un seguimiento del progreso de transformación del índice mediante uno de los SDK.
Consultas ORDER BY en varias propiedades:
Las consideraciones siguientes se usan cuando se utilizan índices compuestos para las consultas con una cláusula ORDER BY
con dos o más propiedades:
Si las rutas de acceso del índice compuesto no coinciden con la secuencia de las propiedades de la cláusula
ORDER BY
, el índice compuesto no puede admitir la consulta.El orden de las rutas de acceso del índice compuesto (ascendente o descendente) también debe coincidir con el valor de
order
de la cláusulaORDER BY
.El índice compuesto también admite una cláusula
ORDER BY
con el orden inverso en todas las rutas de acceso.
Tenga en cuenta el ejemplo siguiente, en el que se define un índice compuesto en las propiedades name, age y _ts:
Índice compuesto | Consulta ORDER BY de ejemplo |
¿Es compatible con el índice compuesto? |
---|---|---|
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age asc |
Yes |
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.age ASC, c.name asc |
No |
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.name DESC, c.age DESC |
Yes |
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age DESC |
No |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age ASC, timestamp ASC |
Yes |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age ASC |
No |
Debe personalizar la directiva de indexación para que pueda atender todas las consultas ORDER BY
necesarias.
Consultas con filtros en varias propiedades
Si una consulta tiene filtros en dos o más propiedades, puede resultar útil crear un índice compuesto para estas propiedades.
Por ejemplo, considere la siguiente consulta que tiene un filtro de igualdad y uno de intervalo:
SELECT *
FROM c
WHERE c.name = "John" AND c.age > 18
Esta consulta es más eficaz, ya que tarda menos tiempo y consume menos RU si es capaz de aplicar un índice compuesto en (name ASC, age ASC)
.
Las consultas con varios filtros de intervalo también se pueden optimizar con un índice compuesto. Sin embargo, cada índice compuesto individual solo puede optimizar un único filtro de intervalo. Los filtros de intervalo incluyen >
, <
, <=
, >=
y !=
. El filtro de intervalo debe definirse en último lugar en el índice compuesto.
Considere la consulta siguiente con un filtro de igualdad y dos de intervalo:
SELECT *
FROM c
WHERE c.name = "John" AND c.age > 18 AND c._ts > 1612212188
Esta consulta es más eficaz con un índice compuesto en (name ASC, age ASC)
y (name ASC, _ts ASC)
. Sin embargo, la consulta no utilizaría ningún índice compuesto en (age ASC, name ASC)
porque las propiedades con los filtros de igualdad primero deben definirse en el índice compuesto. Se requieren dos índices compuestos independientes en lugar de un único índice compuesto en (name ASC, age ASC, _ts ASC)
, ya que cada índice compuesto solo puede optimizar un único filtro de intervalo.
Las consideraciones siguientes se usan cuando se crean índices compuestos para las consultas con filtros en varias propiedades:
- Las expresiones de filtro pueden utilizar varios índices compuestos.
- Las propiedades del filtro de la consulta deben coincidir con las del índice compuesto. Si una propiedad se encuentra en el índice compuesto pero no se incluye en la consulta como filtro, la consulta no utilizará el índice compuesto.
- Si una consulta tiene otras propiedades en el filtro que no están definidas en un índice compuesto, se usa una combinación de índices compuestos y de intervalos para evaluar la consulta. De este modo, se requieren menos RU que si se usan exclusivamente los índices de intervalo.
- Si una propiedad tiene un filtro de intervalo (
>
,<
,<=
,>=
o!=
), esta propiedad se debe definir en último lugar en el índice compuesto. Si una consulta tiene más de un filtro de intervalo, puede aprovechar varios índices compuestos. - Al crear un índice compuesto para optimizar las consultas con varios filtros, el valor de
ORDER
del índice compuesto no tiene ningún impacto en los resultados. Esta propiedad es opcional.
Tenga en cuenta los ejemplos siguientes, en los que se define un índice compuesto en las propiedades name, age y timestamp:
Índice compuesto | Consulta de ejemplo | ¿Es compatible con el índice compuesto? |
---|---|---|
(name ASC, age ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age = 18 |
Yes |
(name ASC, age ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age > 18 |
Yes |
(name ASC, age ASC) |
SELECT COUNT(1) FROM c WHERE c.name = "John" AND c.age > 18 |
Yes |
(name DESC, age ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age > 18 |
Yes |
(name ASC, age ASC) |
SELECT * FROM c WHERE c.name != "John" AND c.age > 18 |
No |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age = 18 AND c.timestamp > 123049923 |
Yes |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age < 18 AND c.timestamp = 123049923 |
No |
(name ASC, age ASC) and (name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age < 18 AND c.timestamp > 123049923 |
Yes |
Consultas con un filtro y ORDER BY
Si una consulta aplica un filtro en una o más propiedades y tiene propiedades diferentes en la cláusula ORDER BY, puede resultar útil agregar las propiedades del filtro a la cláusula ORDER BY
.
Por ejemplo, al agregar las propiedades del filtro a la cláusula ORDER BY
, se podría volver a escribir la siguiente consulta para aprovechar un índice compuesto:
Consulta mediante un índice de intervalo:
SELECT *
FROM c
WHERE c.name = "John"
ORDER BY c.timestamp
Consulta mediante un índice de compuesto:
SELECT *
FROM c
WHERE c.name = "John"
ORDER BY c.name, c.timestamp
Las mismas optimizaciones de consulta se pueden generalizar para cualquier consulta de ORDER BY
con filtros, teniendo en cuenta que los índices compuestos individuales solo pueden admitir, como máximo, un filtro de intervalo.
Consulta mediante un índice de intervalo:
SELECT *
FROM c
WHERE c.name = "John" AND c.age = 18 AND c.timestamp > 1611947901
ORDER BY c.timestamp
Consulta mediante un índice de compuesto:
SELECT *
FROM c
WHERE c.name = "John" AND c.age = 18 AND c.timestamp > 1611947901
ORDER BY c.name, c.age, c.timestamp
Además, puede usar índices compuestos para optimizar las consultas con funciones del sistema y ORDER BY:
Consulta mediante un índice de intervalo:
SELECT *
FROM c
WHERE c.firstName = "John" AND Contains(c.lastName, "Smith", true)
ORDER BY c.lastName
Consulta mediante un índice de compuesto:
SELECT *
FROM c
WHERE c.firstName = "John" AND Contains(c.lastName, "Smith", true)
ORDER BY c.firstName, c.lastName
Las consideraciones siguientes se aplican cuando se crean índices compuestos para optimizar una consulta con un filtro y una cláusula ORDER BY
:
- Si no define ningún índice compuesto en una consulta con un filtro en una propiedad y una cláusula independiente
ORDER BY
mediante una propiedad diferente, la consulta se realizará correctamente. Sin embargo, el costo de RU de la consulta se puede reducir con un índice compuesto, especialmente si la propiedad de la cláusulaORDER BY
tiene una cardinalidad alta. - Si la consulta aplica filtros en las propiedades, estas propiedades deben incluirse en primer lugar en la cláusula
ORDER BY
. - Si la consulta aplica filtros en varias propiedades, los filtros de igualdad deben ser las primeras propiedades de la cláusula
ORDER BY
. - Si la consulta filtra varias propiedades, puede tener un máximo de un filtro de intervalo o una función del sistema utilizada por índice compuesto. La propiedad usada en el filtro de intervalo o en la función del sistema se debe definir en último lugar en el índice compuesto.
- Todavía se aplican todas las consideraciones para crear índices compuestos para consultas
ORDER BY
con varias propiedades, así como consultas con filtros en varias propiedades.
Índice compuesto | Consulta ORDER BY de ejemplo |
¿Es compatible con el índice compuesto? |
---|---|---|
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" ORDER BY c.name ASC, c.timestamp ASC |
Yes |
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.timestamp > 1589840355 ORDER BY c.name ASC, c.timestamp ASC |
Yes |
(timestamp ASC, name ASC) |
SELECT * FROM c WHERE c.timestamp > 1589840355 AND c.name = "John" ORDER BY c.timestamp ASC, c.name ASC |
No |
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" ORDER BY c.timestamp ASC, c.name ASC |
No |
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" ORDER BY c.timestamp ASC |
No |
(age ASC, name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.age = 18 and c.name = "John" ORDER BY c.age ASC, c.name ASC,c.timestamp ASC |
Yes |
(age ASC, name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.age = 18 and c.name = "John" ORDER BY c.timestamp ASC |
No |
Consultas con un filtro y un agregado
Si una consulta aplica filtros a una o varias propiedades y tiene una función del sistema de agregado, puede resultar útil crear un índice compuesto para las propiedades del filtro y de la función del sistema de agregado. Esta optimización se aplica a las funciones del sistema SUM y AVG.
Las consideraciones siguientes se aplican al crear índices compuestos para optimizar una consulta con un filtro o una función del sistema de agregado.
- Los índices compuestos son opcionales cuando se ejecutan consultas con agregados. Sin embargo, el coste de RU de la consulta se puede reducir a menudo con un índice compuesto.
- Si la consulta aplica filtros por varias propiedades, los filtros de igualdad deben ser las primeras propiedades del índice compuesto.
- Puede tener como máximo un filtro de intervalo por índice compuesto y debe estar en la propiedad de la función del sistema de agregado.
- La propiedad de la función del sistema de agregado se debe definir en último lugar en el índice compuesto.
- El
order
(ASC
oDESC
) no importa.
Índice compuesto | Consulta de ejemplo | ¿Es compatible con el índice compuesto? |
---|---|---|
(name ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" |
Yes |
(timestamp ASC, name ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" |
No |
(name ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name > "John" |
No |
(name ASC, age ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" AND c.age = 25 |
Yes |
(age ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" AND c.age > 25 |
No |
Índices compuestos con un carácter comodín de matriz
A continuación se muestra un ejemplo de un índice compuesto que contiene un carácter comodín de matriz.
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{
"path":"/*"
}
],
"excludedPaths":[],
"compositeIndexes":[
[
{"path":"/familyname", "order":"ascending"},
{"path":"/children/[]/age", "order":"descending"}
]
]
}
Una consulta de ejemplo que puede beneficiarse de este índice compuesto es:
SELECT r.id
FROM root r
JOIN ch IN r.children
WHERE r.familyname = 'Anderson' AND ch.age > 20
Modificación de la directiva de indexación
Se puede actualizar en cualquier momento una directiva de indexación de un contenedor mediante Azure Portal o uno de los SDK admitidos. Una actualización de la directiva de indexación desencadena una transformación del índice antiguo al nuevo, que se realiza en línea y en local (por lo que no se consume ningún espacio de almacenamiento adicional durante la operación). La directiva de indexación antigua se transforma eficientemente en la nueva directiva sin que ello afecte a la disponibilidad de escritura, la disponibilidad de lectura ni al rendimiento aprovisionado en el contenedor. La transformación del índice es una operación asincrónica, y el tiempo que tarda en completarse depende del rendimiento aprovisionado, el número de elementos y su tamaño. Si es necesario realizar varias actualizaciones de directivas de indexación, se recomienda realizar todos los cambios en una sola operación para que la transformación del índice se complete lo antes posible.
Importante
La transformación de índice es una operación que consume unidades de solicitud.
Nota:
Puede realizar un seguimiento del progreso de la transformación del índice en Azure Portal o mediante uno de los SDK.
No afecta a la disponibilidad de escritura durante las transformaciones del índice. La transformación del índice usa las RU aprovisionadas, pero en una prioridad más baja que las consultas u operaciones de CRUD.
No afecta a la disponibilidad de lectura al agregar nuevas rutas de acceso indexadas. Las consultas solo usan nuevas rutas de acceso indexadas una vez que termina una transformación del índice. Es decir, al agregar una nueva ruta de acceso indexada, las consultas que se benefician de ella tienen el mismo rendimiento antes y durante la transformación del índice. Una vez terminada la transformación del índice, el motor de consultas comienza a usar las nuevas rutas de acceso indexadas.
Al quitar rutas de acceso indexadas, debe agrupar todos los cambios en una transformación de directiva de indexación. Si quita varios índices y lo hace en un único cambio de directiva de indexación, el motor de consulta proporciona resultados coherentes y completos durante la transformación del índice. Sin embargo, si elimina los índices a través de varios cambios de directiva de indexación, el motor de consulta no proporcionará resultados coherentes o completos hasta que se completen todas las transformaciones del índice. La mayoría de los desarrolladores no coloca los índices e intenta ejecutar consultas que usan esos índices de inmediato, por lo que, en la práctica, esta situación es poco probable.
Cuando se coloca una ruta de acceso indexada, el motor de consultas deja de usarla inmediatamente y, en su lugar, realiza un examen completo.
Nota:
Siempre que sea posible, debe intentar agrupar varios cambios de indexación en una única modificación de directiva de indexación.
Importante
La eliminación de un índice tiene efecto inmediato, mientras que la adición de un nuevo índice lleva cierto tiempo, ya que requiere una transformación de indexación. Al reemplazar un índice por otro (por ejemplo, reemplazar un solo índice de propiedad por un índice compuesto), asegúrese de agregar primero el nuevo índice y, a continuación, esperar a que se complete la transformación del índice antes de quitar el índice anterior de la directiva de indexación. De lo contrario, esto afectará negativamente a la capacidad de consultar el índice anterior y podría interrumpir las cargas de trabajo activas que hagan referencia al índice anterior.
Directivas de indexación y TTL
El uso de la característica Período de vida (TTL) requiere indexación. Esto significa que:
- No es posible activar el TTL en un contenedor en el que se establece el modo de indexación en
none
. - No es posible establecer el modo de indexación en None en un contenedor donde el TTL está activado.
En escenarios donde no es necesario indexar ninguna ruta de acceso de propiedad, pero es necesario el TTL, puede usar una directiva de indexación con un modo de indexación con el modo establecido en consistent
, sin rutas de acceso incluidas y con /*
como la única ruta de acceso excluida.