Ir a la consola

Tipos de índices de 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. Además de la cantidad de campos indexados, los índices de campo único y compuestos se administran de manera distinta.

Í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 usa estos índices para realizar muchas consultas básicas. Para administrar los índices de campo único, puedes configurar la indexación automática de tu base de datos y las exenciones de índices.

Indexación automática

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

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

  • En los campos de mapa, Cloud Firestore crea un índice ascendente con alcance de colección 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 con alcance de colección.

  • Según la configuración predeterminada, no se mantienen los índices de campo único con alcance del grupo de colección.

Exenciones de índices de campo único

Para eximir un campo de tu configuración de indexación automática, crea una exención del índice de campo único. Esta opción anula la configuración de índice automático de la base de datos. Una exención puede habilitar un índice de campo único que, de lo contrario, se inhabilitaría por tu configuración de indexación automática, o viceversa. Consulta las recomendaciones de indexación para saber en qué casos podrían ser útiles las exenciones.

Si creas una exención de un índice de campo único para un campo de mapa, sus subcampos heredarán esta configuración. Sin embargo, puedes definir exenciones de índices de campo único para subcampos específicos. Si borras la exención de un subcampo, este heredará la configuración de la exención principal, si tienes una, o, de lo contrario, heredará la de la base de datos.

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

Í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.

Cloud Firestore usa índices compuestos para admitir consultas que no se pueden realizar en un índice de campo único.

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 compilas 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 compuestos, consulta Administra índices.

Modos de índice y alcances de las consultas

Los índices de campo único y los compuestos se configuran de manera distinta, pero ambos requieren que ajustes los modos de índice y alcances de las consultas.

Modos de índice

Cuando se define un índice, se selecciona un modo de índice para cada campo indexado. El modo de índice de cada campo admite cláusulas específicas de consultas en ese campo. Puedes seleccionar las siguientes opciones:

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 array_contains en el campo.

Alcances de las consultas

Cada índice se limita a una colección o a un grupo de colecciones. Esto se conoce como el alcance de la consulta del índice:

Alcance de la colección
Según la configuración predeterminada, Cloud Firestore crea índices con alcance de colección. Estos índices admiten consultas que muestran resultados de una sola colección.

Alcance del grupo de colección
Un grupo de colección incluye todas las colecciones con el mismo ID. Para ejecutar una consulta del grupo de colección que muestre resultados ordenados o filtrados de un grupo de colección, debes crear un índice correspondiente con el alcance del grupo de colección.

Ejemplo de indexación

Cloud Firestore crea los índices de campo único 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 siguientes ejemplos desde la perspectiva de la creación de índices. En el siguiente fragmento, 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"] });

Suponiendo que se tiene la configuración de indexación automática predeterminada, Cloud Firestore actualiza un índice de campo único ascendente y uno descendente por cada campo que no sea de arreglo y un índice de campo único con contenido del arreglo para el campo del arreglo. Cada fila de la siguiente tabla representa una entrada en un índice de campo único:

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

Consultas compatibles con los índices de campo único

Puedes usar estos índices de campo único 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 necesitas ordenar según otro campo, debes crear un índice compuesto para la consulta.

Consultas compatibles con los índices compuestos

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 Alcance de la consulta
cities arrow_upward (o arrow_downward) country, arrow_upward population Colección

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 Alcance de la consulta
cities arrow_upward country, arrow_upward population Colección
cities arrow_upward country, arrow_downward population Colección

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 Alcance de la consulta
cities array-contains tags, arrow_upward (o arrow_downward) capital Colección

Consultas compatibles con los índices del grupo de colección

Para demostrar un índice con alcance del grupo de colección, imagina que agregas una subcolección landmarks a algunos documentos de city:

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

citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Bridge",
    category : "bridge" });
citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Park",
    category : "park" });

citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Gallery of Art",
    category : "museum" });
citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Mall",
    category : "park" });

Si usas el siguiente índice de campo único con alcance de colección, puedes consultar por los puntos de referencia de park de una ciudad en específico:

Colección Campos indexados Alcance de la consulta
landmarks arrow_upward (o arrow_downward) category Colección
Web
citiesRef.doc("SF").collection("landmarks").where("category", "==", "park")

Ahora, imagina que te interesan los puntos de referencia de park de todas las ciudades. Para realizar esta consulta en un grupo que tenga todas las colecciones de landmarks, debes habilitar el índice de campo único landmarks con el alcance del grupo de colección:

Colección Campos indexados Alcance de la consulta
landmarks arrow_upward (o arrow_downward) category Grupo de colección

Con este índice habilitado, puedes consultar el grupo de colección landmarks:

Web
var landmarksGroupRef = db.collectionGroup("landmarks");

landmarksGroupRef.where("category", "==", "park")

Para realizar una consulta en un grupo de colección que muestre resultados ordenados o filtrados, debes habilitar un índice de campo único o compuesto correspondiente con el alcance del grupo de colección. Sin embargo, las consultas que no ordenan ni filtran los comentarios, no requieren definiciones adicionales del índice.

Por ejemplo, puedes ejecutar la siguiente consulta en el grupo de colección sin habilitar un índice adicional:

Web
db.collectionGroup("landmarks").get()

Í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 Alcance de la consulta
restaurants arrow_upward category, arrow_upward star_rating Colección
restaurants arrow_upward city, arrow_upward star_rating Colección
restaurants arrow_upward category, arrow_upward city, arrow_upward star_rating Colección
restaurants arrow_upward category, arrow_upward city, arrow_upward editors_pick, arrow_upward star_rating Colección

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 Alcance de la consulta
restaurants arrow_upward category, arrow_upward star_rating Colección
restaurants arrow_upward city, arrow_upward star_rating Colección
restaurants arrow_upward editors_pick, arrow_upward star_rating Colección

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.