Tipos de índices no Cloud Firestore

Os índices são um fator importante no desempenho de um banco de dados. Semelhantes aos índices de livros que correlacionam os tópicos às páginas, os índices de bancos de dados referenciam os itens aos locais deles no banco de dados. Quando você faz uma consulta em um banco de dados, ele pode usar um índice para procurar rapidamente os locais dos itens solicitados.

Veja nesta página os dois tipos de índices usados pelo Cloud Firestore: índices de campo único e índices compostos.

Um índice para cada consulta

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

Menos gerenciamento de índices, mais desenvolvimento de apps

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

Tipos de índice

O Cloud Firestore usa dois tipos de índices, de campo único e compostos. Ambos os tipos são definidos exclusivamente pelos campos que indexam e pelo modo de índice em cada campo.

Modos de índice

Ao definir um índice, você seleciona um modo de índice para cada campo indexado. Existem três opções para o modo de índice:

Modo de índice Descrição
Crescente arrow_upward Compatível com cláusulas de consulta <, <=, ==, >= e > no campo e com a classificação dos resultados em ordem crescente com base no valor desse campo.
Decrescente arrow_downward Compatível com cláusulas de consulta <, <=, ==, >= e > no campo e com a classificação dos resultados em ordem decrescente com base no valor desse campo.
Matriz contém Compatível com cláusulas de consulta array_contains no campo.

Assim, por exemplo, um índice no campo foo no modo crescente é diferente de um índice no campo foo no modo decrescente.

Índices de campo único

Um índice de campo único armazena um mapeamento ordenado de todos os documentos em um conjunto com um campo específico. Cada entrada em um índice de campo único registra o valor de um documento para um campo específico e o local do documento no banco de dados. O Cloud Firestore mantém automaticamente índices de campo único para cada campo em um documento.

Indexação automática

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

  • Para cada campo que não seja de matriz ou de mapa, o Cloud Firestore define dois índices de campo único, um em modo crescente e um em modo decrescente.

  • Para cada campo de mapa, o Cloud Firestore cria um índice crescente e um índice decrescente para cada subcampo no mapa.

  • Para cada campo de matriz em um documento, o Cloud Firestore cria e mantém um índice "matriz contém".

Isenções de índice de campo único

Você pode isentar um campo da indexação automática ao criar 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. Para ver casos em que as isenções podem ser úteis, consulte as práticas recomendadas de indexação.

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

Exemplos de consultas compatível com índices de campo único

Ao criar esses índices automaticamente, o Cloud Firestore permite que seu aplicativo efetue rapidamente as consultas mais básicas no banco de dados. Com os índices de campo único, você pode realizar consultas simples com base nos valores de campos e os comparadores <, <=, ==, >= e >. Para campos de matriz, eles permitem que você execute consultas array_contains.

Para ilustrar, veja os exemplos de cities do ponto de vista da criação de índices. No exemplo a seguir, criamos alguns documentos city em um conjunto cities e definimos os campos name, state, country, capital, population e tags para cada um deles:

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

Para cada operação set, o Cloud Firestore atualiza um índice de campo único crescente por campo que não seja de matriz, um índice decrescente de campo único por campo que não seja de matriz e um índice de campo único "matriz contém" para o campo de matriz.

O Cloud Firestore atualiza um índice de campo único "matriz contém" para o campo de matriz e dois índices de campo único por campo que não seja de matriz. Cada linha na tabela a seguir representa uma entrada em um índice de campo único:

Conjunto 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

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

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

Com o índice array_contains, você pode consultar o campo de matriz regions:

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

Você também pode criar consultas compostas com base em igualdades (==):

Web
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 classificar por um campo diferente, crie um índice composto para essa consulta.

Índices compostos

Um índice composto armazena um mapeamento classificado de todos os documentos em uma coleção que contêm vários campos específicos, em vez de apenas um. Um índice composto também define um modo de índice (crescente, descendente ou contém matriz) para cada um dos campos, além de ser classificado com base nesses modos.

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

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

Essas consultas exigem o índice composto abaixo. Observe que, como a consulta usa uma igualdade para o campo country, o modo de índice dele pode ser decrescente ou crescente. Por padrão, as consultas de desigualdade aplicarão uma ordem de classificação crescente com base no campo da cláusula de desigualdade.

Conjunto Campos indexados
cities arrow_upward (ou arrow_downward) country, arrow_upward population

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

Se você fizer a consulta acima sem antes criar o índice necessário, o Cloud Firestore retornará uma mensagem de erro contendo um link que pode ser acessado para criar o índice ausente. Isso acontecerá sempre que você fizer uma consulta não compatível com um índice. Também é possível criar e gerenciar índices compostos manualmente usando o console ou a Firebase CLI. Para mais informações sobre esses processos, consulte Como gerenciar índices.

Se você quiser executar as mesmas consultas, mas com uma ordem de classificação decrescente, será necessário criar outro índice composto na direção decrescente para 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")
Conjunto Campos indexados
cities arrow_upward country, arrow_upward population
cities arrow_upward country, arrow_downward population

Também será necessário criar um índice composto se você quiser combinar uma consulta array_contains com cláusulas adicionais.

Web
citiesRef.where("regions", "array_contains", "east_coast")
         .where("capital", "==", true)
Conjunto Campos indexados
cities array-contains tags, arrow_upward (ou arrow_downward) capital

Índices e preços

Os índices são contabilizados nos custos de armazenamento do seu aplicativo. Para saber mais sobre como é calculado o tamanho do armazenamento para índices, consulte Tamanho da entrada de índices.

Como usar 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 múltiplas cláusulas de igualdade (==) e, opcionalmente, com uma cláusula orderBy, o Cloud Firestore pode reutilizar os índices existentes e mesclar os índices de filtros de igualdade simples para criar os índices compostos necessários a consultas de igualdade maiores.

Você pode reduzir os custos de indexação ao identificar situações em que é possível aproveitar a mesclagem de índices. Por exemplo, imagine um conjunto restaurants para um app de classificação de restaurantes:

  • collections_bookmark restaurants

    • class burgerthyme

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

Agora imagine que esse app use consultas como as mostradas abaixo. Observe que ele usa combinações de cláusulas de igualdade para category, city e editors_pick e sempre aplica a classificação star_rating ascendente:

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

Você poderia criar um índice para cada consulta:

Conjunto 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

Uma solução melhor seria reduzir o número de índices aproveitando o recurso de mesclagem de cláusulas de igualdade do Cloud Firestore:

Conjunto 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

Esse conjunto de índices é menor e também aceita uma consulta adicional:

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

Limites de indexação

Os limites a seguir são aplicáveis aos índices. Para mais informações sobre cotas e limites, consulte Cotas e limites.

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

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

40.000

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

  • número de entradas de índice de campo único
  • número de entradas de índice composto
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 dos seguintes itens 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

    1.500 bytes

    Valores de campo acima de 1500 bytes são truncados. Consultas que envolvem valores de índice 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, você pode querer 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 armazena valores de string longos que você não usa para consulta, é possível reduzir os custos de armazenamento com a isenção da indexação no campo.

    Taxas de gravação altas em uma coleção que contém 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 para a coleção será de 500 gravações por segundo. Se você não fizer consultas com base no campo com valores sequenciais, pode isentar o campo da indexação para ignorar esse limite.

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

    Campos grandes de matriz ou de mapa

    Campos grandes de matriz ou de mapa podem se aproximar do limite de 20.000 entradas de índice por documento. Se você não estiver fazendo consultas com base em um campo grande de matriz ou de mapa, é recomendável isentá-lo da indexação.

    Enviar comentários sobre…

    Precisa de ajuda? Acesse nossa página de suporte.