En esta página se describen los conceptos que debes tener en cuenta al seleccionar los índices de Firestore en el modo Datastore para tu aplicación.
Firestore en el modo de Datastore ofrece un alto rendimiento de las consultas mediante el uso de índices para todas las consultas. El rendimiento de la mayoría de las consultas depende del tamaño del conjunto de resultados y no del tamaño total de la base de datos.
Firestore en el modo de Datastore define índices integrados para cada propiedad de una entidad. Estos índices de una sola propiedad admiten muchas consultas sencillas. Firestore en el modo de Datastore admite una función de combinación de índices que permite que tu base de datos combine índices integrados para admitir consultas adicionales. Para las consultas más complejas, debes definir los índices compuestos con antelación.
Esta página se centra en la función de combinación de índices, ya que afecta a dos oportunidades importantes de optimización de índices:
- Acelerar las consultas
- Reducir el número de índices compuestos
En el siguiente ejemplo se muestra la función de combinación de índices.
Filtrar entidades Photo
Supongamos que tienes una base de datos en el modo Datastore con entidades del tipo Photo
:
Foto | ||
---|---|---|
Propiedad | Tipo de valor | Descripción |
owner_id |
Cadena | ID de usuario |
tag |
Array de cadenas | Palabras clave tokenizadas |
size |
Entero |
Enumeración:
|
coloration |
Entero |
Enumeración:
|
Supongamos que necesitas una función de aplicación que permita a los usuarios consultar Photo
entidades basadas en una AND
lógica de lo siguiente:
Hasta tres filtros basados en las propiedades:
owner_id
size
coloration
Una cadena de búsqueda
tag
. La aplicación tokeniza la cadena de búsqueda en etiquetas y añade un filtro para cada etiqueta.Por ejemplo, la aplicación convierte la cadena de búsqueda
outside, family
en la consulta filtrostag=outside
ytag=family
.
Si usas los índices integrados y la función de combinación de índices de Firestore en el modo Datastore, puedes cumplir los requisitos de índice de esta función de filtro Photo
sin añadir índices compuestos adicionales.
Los índices integrados de las entidades Photo
admiten consultas de un solo filtro, como las siguientes:
Python
La función de filtro Photo
también requiere consultas que combinen varios filtros de igualdad con un AND
lógico:
Python
Firestore en el modo de Datastore puede admitir estas consultas combinando índices integrados.
Fusión de índices
Firestore en modo Datastore puede usar la combinación de índices cuando tu consulta y tus índices cumplan todas las restricciones siguientes:
- La consulta solo usa filtros de igualdad (
=
) - No existe ningún índice compuesto que coincida perfectamente con los filtros y el orden de la consulta
- Cada filtro de igualdad coincide con al menos un índice existente con el mismo orden que la consulta.
En esta situación, Firestore en el modo de Datastore puede usar los índices que ya existen para admitir la consulta en lugar de requerir que configures un índice compuesto adicional.
Cuando se ordenan dos o más índices por los mismos criterios, Firestore en el modo Datastore puede combinar los resultados de varias lecturas de índices para encontrar los resultados que sean comunes a todos esos índices. Firestore en el modo de Datastore puede combinar índices integrados porque todos ordenan los valores por clave de entidad.
Al combinar índices integrados, Firestore en el modo de Datastore admite consultas con filtros de igualdad en varias propiedades:
Python
Firestore en modo Datastore también puede combinar los resultados de los índices de varias secciones del mismo índice. Al combinar diferentes secciones del índice integrado de la propiedad tag
, Firestore en modo Datastore admite consultas que combinan varios filtros tag
en un AND
lógico:
Python
Las consultas admitidas por los índices integrados combinados completan el conjunto de consultas necesarias para la función de filtrado Photo
. Ten en cuenta que, para admitir la función de Photo
filtrado, no se han necesitado índices compuestos adicionales.
Al seleccionar los índices óptimos para tu aplicación, es importante que conozcas la función de combinación de índices. La combinación de índices ofrece a Firestore en el modo de Datastore una mayor flexibilidad en las consultas, pero puede afectar al rendimiento. En la siguiente sección se describe el rendimiento de la combinación de índices y cómo mejorar el rendimiento añadiendo índices compuestos.
Encontrar el índice perfecto
El índice se ordena primero por ancestro y, después, por valores de propiedad, en el orden especificado en la definición del índice. El índice compuesto perfecto para una consulta, que permite que la consulta se ejecute de la forma más eficiente, se define en las siguientes propiedades, por orden:
- Propiedades usadas en filtros de igualdad
- Propiedades usadas en los criterios de ordenación
- Propiedades usadas en el filtro
distinctOn
- Propiedades usadas en filtros de intervalo y de desigualdad (que aún no se han incluido en los criterios de ordenación)
- Propiedades usadas en agregaciones y proyecciones (que aún no se han incluido en los criterios de ordenación y en los filtros de intervalo y desigualdad)
De esta forma, se tienen en cuenta todos los resultados de cada ejecución posible de la consulta. Las bases de datos de Firestore en el modo Datastore ejecutan una consulta mediante un índice perfecto siguiendo estos pasos:
- Identifica el índice correspondiente al tipo de consulta, las propiedades de filtro, los operadores de filtro y los criterios de ordenación.
- Analiza desde el principio del índice hasta la primera entidad que cumpla todas o un subconjunto de las condiciones de filtro de la consulta.
- Sigue analizando el índice y devuelve cada entidad que cumpla todas las condiciones del filtro hasta que
- encuentra una entidad que no cumple las condiciones del filtro, o
- llega al final del índice o
- ha recogido el número máximo de resultados solicitado por la consulta
Por ejemplo, echa un vistazo a esta consulta:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority < 3
ORDER BY priority DESC
El índice compuesto perfecto para esta consulta es un índice de claves de entidades de tipo Task
, con columnas para los valores de las propiedades category
y priority
. El índice se ordena primero de forma ascendente por category
y, después, de forma descendente por priority
:
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: desc
Dos consultas del mismo formato pero con valores de filtro diferentes utilizan el mismo índice. Por ejemplo, la siguiente consulta usa el mismo índice que la consulta anterior:
SELECT * FROM Task
WHERE category = 'Work'
AND priority < 5
ORDER BY priority DESC
Para este índice
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: asc
- name: created
direction: asc
El índice anterior puede satisfacer ambas consultas:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority = 5
ORDER BY created ASC
y
SELECT * FROM Task
WHERE category = 'Work'
ORDER BY priority ASC, created ASC
Optimizar la selección de índices
En esta sección se describen las características de rendimiento de la combinación de índices y dos oportunidades de optimización relacionadas con ella:
- Añadir índices compuestos para acelerar las consultas que dependen de índices combinados
- Reduce el número de índices compuestos aprovechando los índices combinados
Rendimiento de la combinación de índices
En una combinación de índices, Firestore en modo Datastore combina los índices de forma eficiente mediante un algoritmo de combinación de zig-zag. Con este algoritmo, el modo Datastore combina las coincidencias potenciales de varias lecturas de índice para generar un conjunto de resultados que coincida con una consulta. La combinación de índices combina los componentes de filtro en el momento de la lectura, en lugar de en el momento de la escritura. A diferencia de la mayoría de las consultas de Firestore en el modo Datastore, cuyo rendimiento depende únicamente del tamaño del conjunto de resultados, el rendimiento de las consultas de combinación de índices depende de los filtros de la consulta y de cuántas coincidencias potenciales considere la base de datos.
El mejor rendimiento de una combinación de índices se produce cuando cada posible coincidencia de un índice cumple los filtros de la consulta. En este caso, el rendimiento es O(R * I)
, donde R
es el tamaño del conjunto de resultados y I
es el número de índices analizados.
El peor rendimiento se produce cuando la base de datos debe tener en cuenta muchas coincidencias posibles, pero pocas de ellas cumplen los filtros de la consulta. En este caso, el rendimiento es O(S)
, donde S
es el tamaño del conjunto más pequeño de entidades potenciales de un solo análisis de índice.
El rendimiento real depende de la forma de los datos. El número medio de entidades que se tienen en cuenta para cada resultado devuelto es O(S/(R * I))
. Las consultas tienen un rendimiento peor cuando muchas entidades coinciden con cada análisis de índice, pero pocas entidades coinciden con la consulta en su conjunto, lo que significa que R
es pequeño y S
es grande.
Hay cuatro factores que mitigan este riesgo:
El planificador de consultas no busca una entidad hasta que sabe que la entidad coincide con toda la consulta.
El algoritmo de zig-zag no necesita encontrar todos los resultados para devolver el siguiente. Si solicitas los 10 primeros resultados, solo pagas la latencia para encontrar esos 10 resultados.
El algoritmo de zigzag omite grandes secciones de resultados falsos positivos. El peor rendimiento solo se produce si los resultados falsos positivos se entrelazan perfectamente (en orden de clasificación) entre las exploraciones.
La latencia depende del número de entidades encontradas en cada análisis de índice, no del número de entidades que coinciden con cada filtro. Como se muestra en la siguiente sección, puede añadir índices compuestos para mejorar el rendimiento de la combinación de índices.
Acelerar una consulta de combinación de índices
Cuando Firestore en el modo de Datastore combina índices, cada análisis de índice suele corresponderse con un solo filtro en la consulta. Puedes mejorar el rendimiento de las consultas añadiendo índices compuestos que coincidan con varios filtros de la consulta.
Considera esta consulta:
Python
Cada filtro se asigna a un análisis de índice en los siguientes índices integrados:
Index(Photo, owner_id) Index(Photo, size) Index(Photo, tag)
Si añade el índice compuesto Index(Photo, owner_id, size)
, la consulta se asigna a dos análisis de índice en lugar de tres:
# Satisfies both 'owner_id=username' and 'size=2'
Index(Photo, owner_id, size)
Index(Photo, tag)
Imagina una situación en la que hay muchas imágenes grandes, muchas imágenes en blanco y negro, pero pocas imágenes panorámicas grandes. Una consulta que filtre imágenes panorámicas y en blanco y negro será lenta si combina índices integrados:
Python
Para mejorar el rendimiento de las consultas, puede reducir el valor de S
(el conjunto más pequeño de entidades en un solo análisis de índice) en O(S/(R * I))
añadiendo el siguiente índice compuesto:
Index(Photo, size, coloration)
En comparación con el uso de dos índices integrados, este índice compuesto produce menos resultados posibles para los mismos dos filtros de consulta. Este enfoque mejora considerablemente el rendimiento a costa de un índice más.
Reducir el número de índices compuestos con la combinación de índices
Aunque los índices compuestos que coinciden exactamente con los filtros de una consulta ofrecen el mejor rendimiento, no siempre es recomendable o posible añadir un índice compuesto para cada combinación de filtros. Debes equilibrar tus índices compuestos con lo siguiente:
Límites de los índices compuestos:
Límite Importe Número máximo de índices compuestos en una base de datos -
200 cuando no hayas habilitado la facturación en tu proyecto de Google Cloud .
Si necesitas una cuota mayor, deberás habilitar la facturación de tu Google Cloud proyecto.
-
1000 cuando habilites la facturación de tu proyecto de Google Cloud .
Puedes ponerte en contacto con el equipo de Asistencia para solicitar un aumento de este límite.
Suma máxima de los tamaños de las entradas del índice compuesto de una entidad 2 MiB Suma máxima de los siguientes elementos de una entidad: - Número de valores de propiedades indexadas
- Número de entradas de índices compuestos
20.000 -
- Costes de almacenamiento de cada índice adicional.
- Efectos en la latencia de escritura.
Los problemas de indexación suelen surgir con campos de varios valores, como la propiedad tag
de las entidades Photo
.
Por ejemplo, supongamos que la función de filtrado Photo
ahora debe admitir cláusulas de orden descendente basadas en cuatro propiedades adicionales:
Foto | ||
---|---|---|
Propiedad | Tipo de valor | Descripción |
date_added |
Entero | Fecha y hora |
rating |
Flotante | Valoración total de los usuarios |
comment_count |
Entero | Número de comentarios |
download_count |
Entero | Número de descargas |
Si no tienes en cuenta el campo tag
, puedes seleccionar índices compuestos que coincidan con todas las combinaciones de filtros Photo
:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -comments) Index(Photo, size, -date_added) Index(Photo, size, -comments) ... Index(Photo, owner_id, size, -date_added) Index(Photo, owner_id, size, -comments) ... Index(Photo, owner_id, size, coloration, -date_added) Index(Photo, owner_id, size, coloration, -comments)
El número total de índices compuestos es:
2^(number of filters) * (number of different orders) = 2 ^ 3 * 4 = 32 composite indexes
Si intentas admitir hasta 3 filtros tag
, el número total de índices compuestos es el siguiente:
2 ^ (3 + 3 tag filters) * 4 = 256 indexes.
Los índices que incluyen propiedades de varios valores, como tag
, también provocan problemas de explosión de índices que aumentan los costes de almacenamiento y la latencia de escritura.
Para admitir filtros en el campo tag
de esta función, puedes reducir el número total de índices usando índices combinados. El siguiente conjunto de índices compuestos es el mínimo necesario para admitir la función de filtrado Photo
con orden:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -rating) Index(Photo, owner_id, -comments) Index(Photo, owner_id, -downloads) Index(Photo, size, -date_added) Index(Photo, size, -rating) Index(Photo, size, -comments) Index(Photo, size, -downloads) ... Index(Photo, tag, -date_added) Index(Photo, tag, -rating) Index(Photo, tag, -comments) Index(Photo, tag, -downloads)
El número de índices compuestos definidos es:
(number of filters + 1) * (number of orders) = 7 * 4 = 28
La combinación de índices también ofrece las siguientes ventajas:
- Permite que una entidad
Photo
admita hasta 1000 etiquetas sin límite en el número de filtrostag
por consulta. - Reduce el número total de índices, lo que reduce los costes de almacenamiento y la latencia de escritura.
Seleccionar índices para tu aplicación
Puede seleccionar los índices óptimos para su base de datos en modo Datastore de dos formas:
Usar la combinación de índices para admitir consultas adicionales
- Requiere menos índices compuestos
- Reduce el coste de almacenamiento por entidad
- Mejora la latencia de escritura
- Evita que los índices se descontrolen
- El rendimiento depende de la forma de los datos
Definir un índice compuesto que coincida con varios filtros en una consulta
- Mejora el rendimiento de las consultas
- Rendimiento de las consultas constante que no depende de la forma de los datos
- Debe mantenerse por debajo del límite de índices compuestos
- Aumento del coste de almacenamiento por entidad
- Latencia de escritura aumentada
Al determinar los índices óptimos para tu aplicación, la respuesta puede cambiar a medida que lo hace la forma de tus datos. El muestreo del rendimiento de las consultas te permite hacerte una idea de las consultas habituales de tu aplicación y de las lentas. Con esta información, puedes añadir índices para mejorar el rendimiento de las consultas comunes y lentas.