Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Tipos de índice no Cloud Firestore

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Os índices são um fator importante no desempenho de um banco de dados. Muito parecido com o índice de um livro que mapeia tópicos em um livro para números de página, um índice de banco de dados mapeia os itens em um banco de dados para suas localizações no banco de dados. Quando você envia uma consulta a um banco de dados, o banco de dados pode usar um índice para pesquisar rapidamente os locais dos itens solicitados.

Esta página descreve os dois tipos de índices que o Cloud Firestore usa, índices de campo único e índices compostos .

Um índice por trás de cada consulta

Se não houver índice para uma consulta, a maioria dos bancos de dados rastreia seu conteúdo item por item, um processo lento que fica ainda mais lento à medida que o banco de dados cresce. O Cloud Firestore garante alto desempenho de consulta usando índices para todas as consultas. Como resultado, o desempenho da consulta depende do tamanho do conjunto de resultados e não do número de itens no banco de dados.

Menos gerenciamento de índices, mais desenvolvimento de aplicativos

O Cloud Firestore inclui recursos que reduzem o tempo necessário para gerenciar índices. Os índices necessários para as consultas mais básicas são criados automaticamente para você. À medida que você usa e testa seu aplicativo, o Cloud Firestore ajuda a identificar e criar índices adicionais que seu aplicativo exige.

Tipos de índice

O Cloud Firestore usa dois tipos de índices: de campo único e composto . Além do número de campos indexados, os índices de campo único e compostos diferem em como você os gerencia.

Índices de campo único

Um índice de campo único armazena um mapeamento classificado de todos os documentos em uma coleção que contém um campo específico. Cada entrada em um índice de campo único registra o valor de um documento para um campo específico e a localização do documento no banco de dados. O Cloud Firestore usa esses índices para realizar muitas consultas básicas. Você gerencia índices de campo único definindo as configurações de indexação automática do banco de dados e isenções de índice.

Indexação automática

Por padrão, o Cloud Firestore mantém automaticamente índices de campo único para cada campo em um documento e cada subcampo em um mapa. O Cloud Firestore usa as seguintes configurações padrão para índices de campo único:

  • Para cada campo sem matriz e sem mapa, o Cloud Firestore define dois índices de campo único de escopo de coleção , um no modo ascendente e outro no modo descendente.

  • Para cada campo de mapa, o Cloud Firestore cria um índice crescente de escopo de coleção e um índice decrescente para cada subcampo não-matriz e não-mapa no mapa.

  • Para cada campo de matriz em um documento, o Cloud Firestore cria e mantém um índice de array-contém de escopo de coleção.

  • Índices de campo único com escopo de grupo de coleção não são mantidos por padrão.

Isenções de índice de campo único

Você pode isentar um campo de suas configurações de indexação automática criando uma isenção de índice de campo único. Uma isenção de indexação substitui as configurações de índice automático em todo o banco de dados. Uma isenção pode habilitar um índice de campo único que suas configurações de indexação automática desabilitariam ou desabilitariam um índice de campo único que a indexação automática habilitaria. Para casos em que as isenções podem ser úteis, consulte as práticas recomendadas de indexação .

Se você criar uma isenção de índice de campo único para um campo de mapa, os subcampos do mapa herdarão essas configurações. No entanto, você pode definir isenções de índice de campo único para subcampos específicos. Se você excluir uma isenção para um subcampo, o subcampo herdará as configurações de isenção do pai, se existirem, ou as configurações de todo o banco de dados, se não houver isenções pai.

Para criar e gerenciar isenções de índice de campo único, consulte Como gerenciar índices no Cloud Firestore .

Índices compostos

Um índice composto armazena um mapeamento classificado de todos os documentos em uma coleção, com base em uma lista ordenada de campos a serem indexados.

O Cloud Firestore usa índices compostos para oferecer suporte a consultas que ainda não são compatíveis com índices de campo único.

O Cloud Firestore não cria automaticamente índices compostos como faz para índices de campo único devido ao grande número de combinações de campos possíveis. Em vez disso, o Cloud Firestore ajuda você a identificar e criar índices compostos necessários à medida que você cria seu aplicativo.

Se você tentar a consulta acima sem primeiro criar o índice necessário, o Cloud Firestore retornará uma mensagem de erro contendo um link que você pode seguir para criar o índice ausente. Isso acontece sempre que você tenta uma consulta não suportada por um índice. Você também pode definir e gerenciar índices compostos manualmente usando o console ou a Firebase CLI . Para obter mais informações sobre como criar e gerenciar índices compostos, consulte Gerenciando índices .

Modos de índice e escopos de consulta

Você configura índices de campo único e compostos de maneira diferente, mas ambos exigem que você configure modos de índice e escopos de consulta para seus índices.

Modos de índice

Ao definir um índice, você seleciona um modo de índice para cada campo indexado. O modo de índice de cada campo oferece suporte a cláusulas de consulta específicas nesse campo. Você pode selecionar um dos seguintes modos de índice:

Modo de índice Descrição
Seta ascendente_para Oferece suporte a cláusulas de consulta < , <= , == , >= , > , != , in e not-in no campo e oferece suporte à classificação de resultados em ordem crescente com base nesse valor de campo.
Seta descendente_para Oferece suporte a cláusulas de consulta < , <= , == , >= , > , != , in e not-in no campo e oferece suporte à classificação de resultados em ordem decrescente com base nesse valor de campo.
Matriz contém Suporta cláusulas de consulta array-contains e array-contains-any no campo.

Escopos de consulta

Cada índice tem como escopo uma coleção ou um grupo de coleções. Isso é conhecido como escopo de consulta do índice:

Escopo da coleção
O Cloud Firestore cria índices com escopo de coleção por padrão. Esses índices dão suporte a consultas que retornam resultados de uma única coleção.

Escopo do grupo de coleção
Um grupo de coleção inclui todas as coleções com o mesmo ID de coleção. Para executar uma consulta de grupo de coleção que retorna resultados filtrados ou ordenados de um grupo de coleção, você deve criar um índice correspondente com escopo de grupo de coleção.

Exemplo de indexação

Ao criar automaticamente índices de campo único para você, o Cloud Firestore permite que seu aplicativo suporte rapidamente as consultas de banco de dados mais básicas. Índices de campo único permitem que você execute consultas simples com base em valores de campo e os comparadores < , <= , == , >= , > e in . Para campos de matriz, eles permitem que você execute consultas array-contains e array-contains-any .

Para ilustrar, examine os exemplos a seguir do ponto de vista da criação de índice. O snippet a seguir cria alguns documentos de city em uma coleção de cities e define os campos name , state , country , capital , population e tags para cada documento:

Rede
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"] });

Presumindo as configurações de indexação automática padrão, o Cloud Firestore atualiza um índice de campo único crescente por campo que não é de matriz, um índice de campo único decrescente por campo que não é de matriz e um índice de campo único com matriz para o campo de matriz. Cada linha na tabela a seguir representa uma entrada em um índice de campo único:

Coleção Campo indexado Escopo da consulta
cidades nome Coleção
cidades estado Coleção
cidades país Coleção
cidades capital Coleção
cidades população Coleção
cidades nome Coleção
cidades estado Coleção
cidades país Coleção
cidades capital Coleção
cidades população Coleção
cidades array-contains regiões Coleção

Consultas suportadas por índices de campo único

Usando esses índices de campo único criados automaticamente, você pode executar consultas simples como as seguintes:

Rede
const stateQuery = citiesRef.where("state", "==", "CA");
const populationQuery = citiesRef.where("population", "<", 100000);
const nameQuery = citiesRef.where("name", ">=", "San Francisco");

Você também pode criar e compor consultas in igualdade ( == ):

Rede
citiesRef.where('country', 'in', ["USA", "Japan", "China"])

// Compound equality queries
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA")
         .where("capital", "==", false)
         .where("state", "==", "CA")
         .where("population", "==", 860000)

Se você precisar executar uma consulta composta que usa uma comparação de intervalo ( < , <= , > ou >= ) ou se precisar classificar por um campo diferente, deverá criar um índice composto para essa consulta.

O índice array-contains permite que você consulte o campo da matriz de regions :

Rede
citiesRef.where("regions", "array-contains", "west_coast")
// array-contains-any and array-contains use the same indexes
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])

Consultas suportadas por índices compostos

O Cloud Firestore usa índices compostos para oferecer suporte a consultas compostas ainda não compatíveis com índices de campo único. Por exemplo, você precisaria de um índice composto para as seguintes consultas:

Rede
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)
// in and == clauses use the same index
citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)

Essas consultas exigem o índice composto abaixo. Como a consulta usa uma igualdade ( == ou in ) para o campo de country , você pode usar um modo de índice ascendente ou descendente para esse campo. Por padrão, as cláusulas de desigualdade aplicam uma ordem de classificação crescente com base no campo na cláusula de desigualdade.

Coleção Campos indexados Escopo da consulta
cidades (ou ) país, população Coleção

Para executar as mesmas consultas, mas com uma ordem de classificação decrescente, você precisa de um índice composto adicional na direção decrescente para population :

Rede
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")

citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)
         .orderBy("population", "desc")
Coleção Campos indexados Escopo da consulta
cidades país, população Coleção
cidades country , população Coleção

Você também precisa criar um índice composto para combinar uma consulta array-contains ou array-contains-any com cláusulas adicionais.

Rede
citiesRef.where("regions", "array-contains", "east_coast")
         .where("capital", "==", true)

// array-contains-any and array-contains use the same index
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])
         .where("capital", "==", true)
Coleção Campos indexados Escopo da consulta
cidades array-contém tags, (ou ) capital Coleção

Consultas suportadas por índices de grupo de coleção

Para demonstrar um índice com escopo de grupo de coleções, imagine que você adiciona uma subcoleção de landmarks de referência a alguns dos documentos da city :

Rede
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" });

Usando o seguinte índice de campo único com escopo de coleção, você pode consultar a coleção de pontos de landmarks de uma única cidade com base no campo de category :

Coleção Campos indexados Escopo da consulta
marcos (ou ) Coleção
Rede
citiesRef.doc("SF").collection("landmarks").where("category", "==", "park")
citiesRef.doc("SF").collection("landmarks").where("category", "in", ["park", "museum"])

Agora, imagine que você está interessado em consultar os pontos de referência em todas as cidades. Para executar esta consulta no grupo de coleta que consiste em todas as coleções de landmarks de referência, você deve habilitar um índice de campo único de landmarks de referência com escopo de grupo de coleta:

Coleção Campos indexados Escopo da consulta
marcos (ou ) Grupo de coleção

Com esse índice habilitado, você pode consultar o grupo de coleta de landmarks de referência:

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

landmarksGroupRef.where("category", "==", "park")
landmarksGroupRef.where("category", "in", ["park", "museum"])

Para executar uma consulta de grupo de coleção que retorna resultados filtrados ou ordenados, você deve habilitar um índice de campo único ou composto correspondente com escopo de grupo de coleção. No entanto, as consultas de grupo de coleção que não filtram ou ordenam resultados não exigem definições de índice adicionais.

Por exemplo, você pode executar a seguinte consulta de grupo de coleção sem habilitar um índice adicional:

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

Entradas de índice

Os índices configurados do seu projeto e a estrutura de um documento determinam o número de entradas de índice para um documento. As entradas de índice contam para o limite de contagem de entradas de índice.

O exemplo a seguir demonstra as entradas de índice de um documento.

Documento

/cities/SF

city_name : "San Francisco"
temperatures : {summer: 67, winter: 55}
neighborhoods : ["Mission", "Downtown", "Marina"]

Índices de campo único

  • city_name ASC
  • city_name DESC
  • temperaturas.verão ASC
  • temperaturas.verão DESC
  • temperaturas.inverno ASC
  • temperaturas.inverno DESC
  • bairros Matriz Contém (ASC e DESC)

Índices compostos

  • city_name ASC, bairros ARRAY
  • city_name DESC, bairros ARRAY

Entradas de índice

Essa configuração de indexação resulta nas 18 entradas de índice a seguir para o documento:

Índice Dados indexados
Entradas de índice de campo único
city_name ASC city_name: "São Francisco"
city_name DESC city_name: "São Francisco"
temperaturas.verão ASC temperaturas.verão: 67
temperaturas.verão DESC temperaturas.verão: 67
temperaturas.inverno ASC temperaturas.inverno: 55
temperaturas.inverno DESC temperaturas.inverno: 55
bairros Matriz Contém ASC bairros: "Missão"
bairros Matriz Contém DESC bairros: "Missão"
bairros Matriz Contém ASC bairros: "Centro"
bairros Matriz Contém DESC bairros: "Centro"
bairros Matriz Contém ASC bairros: "Marina"
bairros Matriz Contém DESC bairros: "Marina"
Entradas de índice composto
city_name ASC, bairros ARRAY city_name: "São Francisco", bairros: "Missão"
city_name ASC, bairros ARRAY city_name: "San Francisco", bairros: "Downtown"
city_name ASC, bairros ARRAY city_name: "São Francisco", bairros: "Marina"
city_name DESC, bairros ARRAY city_name: "São Francisco", bairros: "Missão"
city_name DESC, bairros ARRAY city_name: "San Francisco", bairros: "Downtown"
city_name DESC, bairros ARRAY city_name: "São Francisco", bairros: "Marina"

Índices e preços

Os índices contribuem para os custos de armazenamento de seu aplicativo. Para saber mais sobre como o tamanho do armazenamento para índices é calculado, consulte Tamanho da entrada do índice .

Aproveitando a mesclagem de índices

Embora o Cloud Firestore use um índice para cada consulta, ele não exige necessariamente um índice por consulta. Para consultas com várias cláusulas de igualdade ( == ) e, opcionalmente, uma cláusula orderBy , o Cloud Firestore pode reutilizar índices existentes. O Cloud Firestore pode mesclar os índices para filtros de igualdade simples para criar os índices compostos necessários para consultas de igualdade maiores.

Você pode reduzir os custos de indexação identificando situações em que pode aproveitar a mesclagem de índices. Por exemplo, imagine uma coleção de restaurants para um aplicativo de classificação de restaurantes:

  • restaurantes

    • hamburguer

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

Agora, imagine que este aplicativo usa consultas como as abaixo. Observe que o aplicativo usa combinações de cláusulas de igualdade para category , city e editors_pick enquanto sempre classifica por star_rating ascendente :

Rede
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")

Você pode criar um índice para cada consulta:

Coleção Campos indexados Escopo da consulta
restaurantes categoria , star_rating Coleção
restaurantes cidade, star_rating Coleção
restaurantes categoria , city, star_rating Coleção
restaurantes categoria , city, editors_pick, star_rating Coleção

Como uma solução melhor, você pode reduzir o número de índices aproveitando a capacidade do Cloud Firestore de mesclar índices para cláusulas de igualdade:

Coleção Campos indexados Escopo da consulta
restaurantes categoria , star_rating Coleção
restaurantes cidade, star_rating Coleção
restaurantes editors_pick, star_rating Coleção

Esse conjunto de índices não é apenas menor, mas também suporta uma consulta adicional:

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

Limites de indexação

Os limites a seguir se aplicam aos índices. Para todas as cotas e limites, consulte Cotas e limites .

Limite Detalhes
Número máximo de índices compostos para um banco de dados 200
Número máximo de configurações de campo único para um banco de dados

200

Um total de 200 configurações de nível de campo são permitidas. Uma configuração de campo pode conter várias configurações para o mesmo campo. Por exemplo, uma isenção de indexação de campo único e uma política de TTL no mesmo campo contam como uma configuração de campo para o limite.

Número máximo de entradas de índice para cada documento

40.000

O número de entradas de índice é a soma do seguinte para um documento:

  • O número de entradas de índice de campo único
  • O número de entradas de índice composto

Para ver como o Cloud Firestore transforma um documento e um conjunto de índices em entradas de índice, consulte este exemplo de contagem de entradas de índice .

Número máximo de campos em um índice composto 100
Tamanho máximo de uma entrada de índice

7,5 KiB

Para ver como o Cloud Firestore calcula o tamanho da entrada do índice, consulte o tamanho da entrada do índice .

Soma máxima dos tamanhos das entradas de índice de um documento

8 MiB

O tamanho total é a soma do seguinte para um documento:

  • A soma do tamanho das entradas de índice de campo único de um documento
  • A soma do tamanho das entradas de índice composto de um documento
  • Tamanho máximo de um valor de campo indexado

    1500 bytes

    Os valores de campo acima de 1500 bytes são truncados. As consultas que envolvem valores de campo truncados podem retornar resultados inconsistentes.

    Práticas recomendadas de indexação

    Para a maioria dos aplicativos, você pode confiar na indexação automática e nos links de mensagens de erro para gerenciar seus índices. No entanto, convém adicionar isenções de campo único nos seguintes casos:

    Caso Descrição
    Campos de string grandes

    Se você tiver um campo de string que geralmente contém valores de string longos que você não usa para consulta, pode reduzir os custos de armazenamento isentando o campo da indexação.

    Altas taxas de gravação para uma coleção contendo documentos com valores sequenciais

    Se você indexar um campo que aumenta ou diminui sequencialmente entre documentos em uma coleção, como um carimbo de data/hora, a taxa máxima de gravação na coleção é de 500 gravações por segundo. Se você não consultar com base no campo com valores sequenciais, poderá isentar o campo da indexação para contornar esse limite.

    Em um caso de uso de IoT com uma alta taxa de gravação, por exemplo, uma coleção contendo documentos com um campo de carimbo de data/hora pode se aproximar do limite de 500 gravações por segundo.

    Campos TTL

    Se você usar políticas TTL (tempo de vida útil) , observe que o campo TTL deve ser um carimbo de data/hora. A indexação em campos TTL é habilitada por padrão e pode afetar o desempenho em taxas de tráfego mais altas. Como prática recomendada, adicione isenções de campo único para seus campos TTL.

    Grande matriz ou campos de mapa

    Grandes campos de matriz ou mapa podem se aproximar do limite de 40.000 entradas de índice por documento. Se você não estiver consultando com base em uma grande matriz ou campo de mapa, isente-o da indexação.