Tipos de índices en Cloud Firestore

Los índices son un factor importante del rendimiento de las bases de datos. Al igual que el índice de un libro que indica en qué página se encuentra cada tema, el índice de una base de datos se encarga de ordenar todos los elementos en su ubicación respectiva. Cuando envías una consulta a una base de datos, esta puede usar el índice para buscar rápidamente los elementos que solicitaste.

En esta página, se describen los dos tipos de índices que usa Cloud Firestore: los de campo único y los compuestos.

Un índice para cada consulta

Si se hace una consulta sin índice, la mayoría de las bases de datos rastreará su contenido elemento por elemento. Este proceso es muy lento y empeora a medida que aumenta el tamaño de la base de datos. Cloud Firestore garantiza un alto rendimiento, ya que usa índices en todas las consultas. Por lo tanto, el rendimiento de las consultas depende del tamaño del conjunto de resultados y no de la cantidad de elementos que se encuentran en la base de datos.

Dedica menos tiempo a la administración de índices y más al desarrollo de apps

Cloud Firestore tiene funciones que reducen el tiempo necesario para administrar los índices, y crea automáticamente los índices necesarios para las consultas más básicas. A medida que usas y pruebas tu app, Cloud Firestore te ayudará a identificar y crear los índices adicionales necesarios.

Tipos de índices

Cloud Firestore usa dos tipos de índices: los de campo único y los compuestos. Ambos se definen de manera única con los campos que indexan y el modo de índice de cada campo.

Modos de índice

Cuando se define un índice, se selecciona un modo de índice para cada campo indexado. Estas son las tres opciones disponibles:

Modo de índice Descripción
Ascendente arrow_upward Admite cláusulas de consulta <, <=, ==, >= y > en el campo, así como el orden ascendente de los resultados según el valor del campo.
Descendente arrow_downward Admite cláusulas de consulta <, <=, ==, >= y > en el campo, así como el orden descendente según el valor del campo.
Contenido del arreglo Admite cláusulas de consulta de array_contains en el campo.

Por ejemplo, un índice de campo foo en modo ascendente es diferente de un índice de campo foo en modo descendente.

Índices de campo único

Un índice de campo único almacena el orden de todos los documentos en una colección con un campo específico. Todas las entradas de un índice de campo único registran el valor de un documento en un campo específico y su ubicación en la base de datos. Cloud Firestore mantiene automáticamente índices de campo único para cada campo de un documento.

Indexación automática

En la configuración predeterminada, Cloud Firestore mantiene automáticamente un índice para cada campo de un documento y cada subcampo de un mapa. Cloud Firestore usa la siguiente configuración para los índices de campo único creados automáticamente:

  • En los campos que no son de arreglo ni de mapa, Cloud Firestore define dos índices de campo único: uno en modo ascendente y otro en modo descendente.

  • En los campos de mapa, Cloud Firestore crea un índice ascendente y uno descendente para cada subcampo que no sea de mapa ni de arreglo.

  • En cada campo de arreglo de un documento, Cloud Firestore crea y mantiene un índice de contenido de arreglo.

Exenciones de índices de campo único

Para eximir a un campo de la indexación automática, crea una exención de índice de campo único. Esta opción anula la configuración de índice automático de la base de datos. Consulta las recomendaciones de indexación para saber en qué casos podrían ser útiles las exenciones.

Para crear y administrar las exenciones de índice de campo único, consulta Administración de índices en Cloud Firestore.

Ejemplos de consultas que admiten índices de campo único

Cloud Firestore crea estos índices de forma automática, lo que permite que tu aplicación admita rápidamente los tipos de consultas de base de datos más básicos. Los índices de campo único te permiten ejecutar consultas simples basadas en los valores de campo y los comparadores <, <=, ==, >= y >. En los campos de arreglo, te permiten ejecutar consultas de array_contains.

A modo de referencia, consulta los ejemplos de cities desde la perspectiva de la creación de índices. En el siguiente ejemplo, se crean algunos documentos de city en una colección de cities y se configuran los campos name, state, country, capital, population y tags para cada documento:

Web
var citiesRef = db.collection("cities");

citiesRef.doc("SF").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000,
    regions: ["west_coast", "norcal"] });
citiesRef.doc("LA").set({
    name: "Los Angeles", state: "CA", country: "USA",
    capital: false, population: 3900000,
    regions: ["west_coast", "socal"] });
citiesRef.doc("DC").set({
    name: "Washington, D.C.", state: null, country: "USA",
    capital: true, population: 680000,
    regions: ["east_coast"] });
citiesRef.doc("TOK").set({
    name: "Tokyo", state: null, country: "Japan",
    capital: true, population: 9000000,
    regions: ["kanto", "honshu"] });
citiesRef.doc("BJ").set({
    name: "Beijing", state: null, country: "China",
    capital: true, population: 21500000,
    regions: ["jingjinji", "hebei"] });

En cada operación set, Cloud Firestore actualiza un índice de campo único ascendente y uno descendente para los campos que no son de arreglo, y un índice de campo único de contenido del arreglo para los campos de arreglo.

Cloud Firestore actualiza un índice de campo único de contenido del arreglo para los campos de arreglo y dos índices de campo único para los campos que no son de arreglo. Cada fila de la siguiente tabla representa una entrada en un índice de campo único:

Colección Campo indexado
cities arrow_upward name
cities arrow_upward state
cities arrow_upward country
cities arrow_upward capital
cities arrow_upward population
cities arrow_downward name
cities arrow_downward state
cities arrow_downward country
cities arrow_downward capital
cities arrow_downward population
cities array-contains regions

Puedes usar estos índices creados automáticamente para ejecutar consultas simples, como esta:

Web
citiesRef.where("state", "==", "CA")
citiesRef.where("population", "<", 100000)
citiesRef.where("name", ">=", "San Francisco")

El índice de array_contains te permite realizar una consulta en el campo de arreglo regions:

Web
citiesRef.where("regions", "array-contains", "west_coast")

También puedes crear consultas compuestas basadas en igualdades (==):

Web
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA").where("capital", "==", false).where("state", "==", "CA").where("population", "==", 860000)

Si necesitas ejecutar una consulta compuesta que use una comparación de rangos (<, <=, > o >=) o si necesitas ordenar según otro campo, debes crear un índice compuesto para la consulta.

Índices compuestos

Un índice compuesto almacena el orden de todos los documentos en una colección que contiene varios campos específicos en lugar de uno solo. También define un modo de índice para cada uno de sus campos (ascendente, descendente o de contenido del arreglo), y el índice se ordena en función de ese modo.

Cloud Firestore usa índices compuestos para admitir consultas compuestas que no se pueden realizar en un índice de campo único. Por ejemplo, debes tener un índice compuesto para realizar las siguientes consultas:

Web
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)

Estas requieren el índice compuesto que se indica a continuación. Debes tener en cuenta que, como la consulta usa una igualdad para el campo country, su modo de índice puede ser ascendente o descendente. En la configuración predeterminada, las consultas con desigualdades aplicarán un orden ascendente según el campo que se indique en la cláusula.

Colección Campos indexados
cities arrow_upward (o arrow_downward) country, arrow_upward population

Cloud Firestore no crea automáticamente los índices compuestos, como sí lo hace con los de campo único, debido a la gran cantidad de combinaciones posibles de los campos. En lugar de eso, Cloud Firestore te ayuda a identificar y crear los índices compuestos necesarios mientras desarrollas tu app.

Si intentas realizar la consulta anterior sin haber creado el índice necesario, Cloud Firestore mostrará un mensaje de error con un vínculo que podrás usar para crear el índice. Esto ocurre cada vez que intentas realizar una consulta que no es compatible con un índice. También puedes definir y administrar los índices compuestos de forma manual con la consola o Firebase CLI. Para obtener más información sobre cómo crear y administrar índices, consulta Administra índices.

Si quieres ejecutar las mismas consultas, pero en orden descendente, necesitas otro índice compuesto en orden descendente para el valor population:

Web
citiesRef.where("country", "==", "USA").orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", "<", 3800000)
         .orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", ">", 690000)
         .orderBy("population", "desc")
Colección Campos indexados
cities arrow_upward country, arrow_upward population
cities arrow_upward country, arrow_downward population

También deberás crear un índice compuesto si quieres combinar una consulta de array_contains con cláusulas adicionales.

Web
citiesRef.where("regions", "array_contains", "east_coast")
         .where("capital", "==", true)
Colección Campos indexados
cities array-contains tags, arrow_upward (or arrow_downward) capital

Índices y precios

Los índices contribuyen a los costos de almacenamiento de tu aplicación. Para obtener más información sobre cómo se calcula el tamaño del almacenamiento de los índices, consulta Tamaño de una entrada del índice.

Cómo aprovechar la combinación de índices

Cloud Firestore usa un índice para cada consulta, pero este no es un requisito. En el caso de las consultas con varias cláusulas de igualdad (==) y, de forma opcional, una cláusula orderBy, Cloud Firestore puede volver a usar los índices existentes. Cloud Firestore puede combinar los índices con filtros de igualdad simples a fin de crear los índices compuestos necesarios para realizar consultas con más cláusulas de igualdad.

A fin de reducir los costos de creación de los índices, identifica las situaciones en las que puedes combinar algunos de ellos. Por ejemplo, imagina una colección de restaurants en una app de calificación de restaurantes:

  • collections_bookmark restaurantes

    • class burgerthyme

      name : "Burger Thyme"
      category : "burgers"
      city : "San Francisco"
      editors_pick : true
      star_rating : 4

Ahora imagina que esta app usa consultas como las que se indican a continuación. Ten en cuenta que la app usa combinaciones de cláusulas de igualdad para category, city y editors_pick, y un orden ascendente por star_rating:

Web
db.collection("restaurants").where("category", "==", "burgers")
                            .orderBy("star_rating")

db.collection("restaurants").where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==" "San Francisco")
                            .where("editors_pick", "==", true )
                            .orderBy("star_rating")

Puedes crear un índice para cada consulta:

Colección Campos indexados
restaurants arrow_upward category, arrow_upward star_rating
restaurants arrow_upward city, arrow_upward star_rating
restaurants arrow_upward category, arrow_upward city, arrow_upward star_rating
restaurants arrow_upward category, arrow_upward city, arrow_upward editors_pick, arrow_upward star_rating

Una mejor opción es aprovechar la función de Cloud Firestore para combinar índices según cláusulas de igualdad a fin de reducir la cantidad de índices:

Colección Campos indexados
restaurants arrow_upward category, arrow_upward star_rating
restaurants arrow_upward city, arrow_upward star_rating
restaurants arrow_upward editors_pick, arrow_upward star_rating

Este conjunto de índices no solo es más pequeño, sino que también admite una consulta adicional:

Web
db.collection("restaurants").where("editors_pick", "==", true)
                            .orderBy("star_rating")

Límites de indexación

Los siguientes límites se aplican a los índices. Consulta Cuotas y límites para obtener más información sobre este tema.

Límite Detalles
Cantidad máxima de índices compuestos permitidos para una base de datos 200
Cantidad máxima de exenciones de índice de campo único para una base de datos 200

Cantidad máxima de entradas de índice permitidas en cada documento

40,000

La cantidad máxima de entradas de índice permitidas en cada documento es la suma de los siguientes elementos:

  • Cantidad de entradas en un índice de campo único
  • Cantidad de entradas en un índice de campo compuesto
Tamaño máximo de una entrada en el índice:

7.5 KiB

Para saber cómo Cloud Firestore calcula el tamaño de las entradas en el índice, consulta Tamaño de una entrada del índice.

Suma máxima de los tamaños de las entradas en un índice de un documento

8 MiB

El tamaño total corresponde a la suma de los siguientes elementos de un documento:

  • La suma del tamaño de las entradas de índice de campo único del documento
  • La suma del tamaño de las entradas de índice compuesto del documento
  • Tamaño máximo del valor de un campo indexado

    1,500 bytes

    Se reducirán los valores de campo que superen los 1,500 bytes. Es posible que las consultas que tengan valores de campo reducidos muestren resultados incoherentes.

    Recomendaciones sobre indexación

    En la mayoría de las apps, puedes confiar en la indexación automática y en los vínculos de los mensajes de error para administrar tus índices. Sin embargo, es posible que quieras agregar exenciones de campo único en los siguientes casos:

    Caso Descripción
    Campos de string grandes

    Si tienes un campo de string que suele tener valores de string largos que no usas para realizar consultas, exime al campo de la indexación a fin de reducir los costos de almacenamiento.

    Tasas altas de escritura en una colección que tiene documentos con valores secuenciales

    Si indexas un campo que aumenta o disminuye secuencialmente entre los documentos de una colección, como una marca de tiempo, la tasa máxima de escritura en la colección es de 500 operaciones de escritura por segundo. Si no realizas consultas basadas en campos con valores secuenciales, puedes eximir al campo de la indexación para pasar ese límite.

    Por ejemplo, en un caso práctico de IoT con una tasa alta de escritura, es posible que una colección de documentos con un campo de marca de tiempo se acerque al límite de 500 operaciones de escritura por segundo.

    Campos grandes de arreglo o de mapa

    Los campos grandes de arreglo o de mapa pueden acercarse al límite de 20,000 entradas de índice por documento. Si no realizas consultas basadas en un campo grande de arreglo o de mapa, debes excluir el campo de la indexación.

    Enviar comentarios sobre…

    ¿Necesitas ayuda? Visita nuestra página de asistencia.