Em todas as consultas do Firestore no modo Datastore, os cálculos dos resultados são feitos usando um ou mais índices. Neles, há chaves de entidade em uma sequência especificada pelas propriedades do índice e, opcionalmente, pelos ancestrais da entidade. Os índices são atualizados para refletir as alterações feitas pelo aplicativo nas entidades. Assim, os resultados corretos de todas as consultas ficam disponíveis sem precisar computar mais nada.
Há dois tipos de índice:
- Índices integrados
- Por padrão, o modo Datastore predefine automaticamente um índice para cada propriedade de cada tipo de entidade. Esses índices de propriedade única são adequados para tipos de consulta simples.
- Índices compostos
- Ordenam valores de diversas propriedades por entidade indexada. Os índices compostos são compatíveis com consultas complexas e são definidos em um arquivo de configuração de índice (
index.yaml
).
Os tipos de índice serão discutidos com mais detalhes posteriormente.
Definição e estrutura dos índices
Um índice é definido em uma lista de propriedades de um determinado tipo de entidade, com uma ordem correspondente (crescente ou decrescente) para cada propriedade. Para o uso com consultas de ancestral, é possível que o índice também inclua opcionalmente os ancestrais de uma entidade.
Um índice contém entradas para cada propriedade nomeada na definição do índice. Cada entrada do índice representa uma entidade que gera um potencial resultado para consultas baseadas no índice. Uma entidade só é incluída no índice quando tem um valor indexado definido para cada propriedade usada no índice. Se a definição do índice se referir a uma propriedade para a qual a entidade não tem valor, essa entidade não vai aparecer no índice e, portanto, nunca será retornada como resultado de nenhuma consulta baseada no índice.
O índice composto é classificado primeiro pelo ancestral e depois pelos valores de propriedade, na ordem especificada na definição do índice. Com base nesse entendimento, é possível criar o índice perfeito, que possibilita consultas eficientes.
Configuração de índice
O Firestore no modo Datastore fornece índices integrados, ou automáticos, para consultas dos seguintes formulários:
- consultas sem tipo usando apenas filtros de chave e ancestral
- consultas usando apenas filtros de igualdade e ancestral
- consultas usando apenas filtros de desigualdade (que são limitados a uma única propriedade)
- consultas usando apenas filtros de ancestral, filtros de igualdade nas propriedades e filtros de desigualdade nas chaves
- consultas sem filtros e apenas uma ordem de classificação em uma propriedade, crescente ou decrescente.
Como exemplo, por padrão, os bancos de dados do modo Datastore predefinem automaticamente dois índices de uma propriedade para cada propriedade de cada tipo de entidade, um em ordem crescente e o outro em ordem decrescente. Se você não quiser que o banco de dados mantenha um índice para uma propriedade, exclua a propriedade dos índices. A exclusão de uma propriedade a remove de qualquer índice composto.
Os índices integrados são suficientes para realizar muitas consultas, como consultas simples de desigualdade e só de igualdade.
Os índices integrados não aparecem na página Índices do console do Google Cloud.
Para fazer consultas mais complexas, um aplicativo precisa definir índices compostos ou manuais. Os índices compostos são obrigatórios nas consultas dos seguintes formulários:
- consultas com filtros de desigualdade e ancestral
- consultas com um ou mais filtros de desigualdade em uma propriedade e um ou mais filtros de igualdade nas outras propriedades
- consultas com uma ordem de classificação nas chaves, em ordem decrescente
- consultas com várias ordens de classificação
- consultas com um ou mais filtros e uma ou mais ordens de classificação
Os índices compostos são definidos no arquivo de configuração de índice (index.yaml
) do aplicativo. Os índices integrados não estão contidos no arquivo de configuração de índice.
Os índices compostos são constituídos por várias propriedades e exigem que cada propriedade não seja excluída dos índices.
Os índices compostos aparecem na página Índices do console do Google Cloud. Não é possível usar o console do Google Cloud para criar ou atualizar índices compostos.
Se o aplicativo tentar fazer uma consulta que não possa ser executada com os índices disponíveis (sejam integrados ou especificados no arquivo de configuração de índice), a consulta falhará.
A API do modo Datastore sugere automaticamente os índices apropriados para a maioria dos aplicativos. Dependendo do uso que o aplicativo faz do modo Datastore e do tamanho e formato dos dados, é possível que os índices sejam ajustados manualmente. Por exemplo, gravar entidades com diversos valores de propriedade pode resultar em um índice em explosão com altos custos de armazenamento e maior latência de gravação.
O emulador do Datastore pode ajudar a facilitar o gerenciamento do arquivo de configuração de índice. Em vez de falhar ao executar uma consulta que requer um índice e não tem um, o emulador do Datastore pode gerar uma configuração de índice que permita que a consulta seja realizada com sucesso. Se o teste local de um aplicativo verificar todas as consultas possíveis que o aplicativo fará usando todas as combinações de filtro e ordem de classificação, as entradas geradas representarão um conjunto de índices completo. Se o teste não verificar todos os formulários de consulta possíveis, você poderá analisar e ajustar o arquivo de configuração de índice antes de atualizar os índices.
Saiba mais sobre index.yaml
em Configuração de índice.
Como implantar ou excluir índices
Quando terminar de alterar o arquivo de configuração de índice, execute o comando gcloud datastore indexes create
para que os índices funcionem.
Saiba mais na seção Como atualizar índices.
Se você implantou índices que não são mais necessários, exclua-os.
Custos de armazenamento e latência de gravação
Os índices são contabilizados nos custos de armazenamento. Em Tamanho da entrada de índice, descrevemos como os índices integrados e compostos contribuem para o tamanho do armazenamento do banco de dados. Use as estatísticas do Firestore no modo Datastore para ver mais informações sobre entradas e tamanho de armazenamento de índices.
Os índices também contribuem para a latência de gravação. Ao atualizar o valor de uma propriedade, o banco de dados também atualiza todos os índices relacionados. Quanto mais índices o banco de dados precisar atualizar, mais tempo levará a operação.
É possível reduzir os custos de armazenamento e melhorar o desempenho de gravação ao excluir índices não utilizados e excluir as propriedades da indexação. Isso também impede que as operações falhem devido aos limites do índice.
Índices e propriedades
Veja a seguir algumas considerações especiais sobre os índices e a relação deles com as propriedades de entidades:
Propriedades com tipos de valor mistos
Quando duas entidades têm propriedades com o mesmo nome, mas tipos de valor diferentes, um índice da propriedade classifica as entidades primeiro por tipo de valor e depois por uma ordenação secundária apropriada a cada tipo. Por exemplo, se duas entidades tiverem uma propriedade chamada age
, uma com valor inteiro e outra com valor de string, a entidade com o valor inteiro sempre precederá aquela com o valor de string quando classificada pela propriedade age
, independentemente dos próprios valores da propriedade.
Isso é especialmente válido no caso de números inteiros e de ponto flutuante, que são tratados como tipos separados pelo modo Datastore. Como todos os números inteiros são classificados antes dos flutuantes, uma propriedade com o valor inteiro 38
é classificada antes de outra com valor de ponto flutuante 37.5
.
Propriedades excluídas
Se você souber que nunca precisará filtrar ou classificar uma determinada propriedade, é possível configurar o modo Datastore para não manter as entradas de índice dessa propriedade excluindo-as dos índices. Isso diminui o custo de execução do seu aplicativo reduzindo o tamanho do armazenamento necessário para as entradas de índice. Isso também pode melhorar a latência da gravação. Uma entidade com uma propriedade excluída se comporta como se a propriedade não estivesse definida: as consultas com um filtro ou ordem de classificação na propriedade excluída nunca corresponderão a essa entidade.
A propriedade description
no exemplo a seguir é excluída dos índices:
C#
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API C# do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Go
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Go do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Java
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Java do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Node.js
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Node.js do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
PHP
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API PHP do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Python
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Ruby
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
GQL
Não relevanteA consulta no exemplo a seguir não retornará resultados se a propriedade description
tiver sido excluída:
C#
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API C# do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Go
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Java
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Java do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Node.js
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
PHP
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API PHP do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Python
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Ruby
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
GQL
# Will not return any results! SELECT * FROM Task WHERE description = 'A task description.'
Posteriormente, é possível alterar a propriedade de volta para indexada.
No entanto, a alteração de uma propriedade de excluída para indexada não afeta qualquer entidade existente que tenha sido criada antes da alteração. A filtragem de consultas na propriedade não retornará essas entidades existentes porque elas não foram gravadas no índice da consulta quando foram criadas. Para tornar as entidades acessíveis pelas próximas consultas, você precisa gravá-las novamente no banco de dados para que sejam inseridas nos índices apropriados. Ou seja, você precisa seguir estas etapas para cada uma dessas entidades atuais:
- Pesquisar (conseguir) a entidade.
- Gravar (colocar) a entidade de volta no banco de dados.
Da mesma forma, a alteração de uma propriedade de indexada para excluída só afeta as entidades gravadas posteriormente no banco de dados. As entradas de índice de qualquer entidade atual com essa propriedade continuarão existindo até que as entidades sejam atualizadas ou excluídas. Para evitar resultados indesejados, você precisa limpar todas as consultas do código que filtram ou classificam pela propriedade (agora excluída).
Limites dos índices
O Firestore no modo Datastore impõe limites ao número e ao tamanho geral das entradas de índice que podem ser associadas a uma única entidade. Esses limites são amplos e a maioria dos aplicativos não é afetada. No entanto, há circunstâncias em que talvez você encontre limites.
Conforme descrito acima, o banco de dados do modo Datastore cria uma entrada em um índice predefinido para cada propriedade de cada entidade, exceto para aquelas explicitamente declaradas como excluídas dos índices. A propriedade também pode ser incluída em outros índices personalizados declarados em seu arquivo de configuração de índice (index.yaml
). Uma entidade terá no máximo uma entrada em cada índice personalizado (para índices não ancestrais) ou uma para cada ancestral da entidade (para índices ancestrais), desde que ela não tenha propriedades de lista. Cada uma dessas entradas de índice precisa ser atualizada sempre que o valor da propriedade for alterado.
Para uma propriedade com um único valor para cada entidade, cada valor possível só precisa ser armazenado uma vez por entidade no índice predefinido da propriedade. Mesmo assim, é possível que uma entidade com um grande número de propriedades com um único valor exceda o limite de tamanho ou de entradas do índice. Da mesma forma, uma entidade com diversos valores para a mesma propriedade exige uma entrada de índice separada para cada valor. Novamente, se houver um grande número de valores possíveis, essa entidade poderá exceder o limite de entradas.
A situação piora no caso de entidades com várias propriedades: cada uma delas pode aceitar diversos valores. Para acomodar esse tipo de entidade, o índice precisa incluir uma entrada para cada combinação possível de valores de propriedade. Os índices personalizados que se referem a várias propriedades, cada uma com diversos valores, podem "explodir" de forma combinatória, exigindo grandes números de entrada para uma entidade com apenas um número relativamente pequeno de valores de propriedade possíveis. Esses índices em explosão tendem a aumentar significativamente o tamanho do armazenamento de uma entidade devido ao grande número de entradas de índice que precisam ser armazenadas. A explosão de índices também pode fazer com que a entidade exceda a contagem de entradas do índice ou o limite de tamanho.
Pense no seguinte código:
C#
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API C# do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Go
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Go do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Java
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java do Cloud Datastore.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Node.js
Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte as Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Node.js do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
PHP
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API PHP do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Python
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Python do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Ruby
Para aprender a instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a API Ruby do Cloud Datastore documentação de referência.
Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
GQL
Não aplicávelEle cria uma entidade Task
com três valores para a propriedade tags
, três valores para a propriedade collaborators
, e created
definido para a data atual. Isso exige nove entradas de índice, uma para cada combinação possível de valores de propriedade:
('fun'
, 'alice'
, NOW()
)
('fun'
, 'bob'
, NOW()
)
('fun'
, 'charlie'
, NOW()
)
('programming'
, 'alice'
, NOW()
)
('programming'
, 'bob'
, NOW()
)
('programming'
, 'charlie'
, NOW()
)
('learn'
, 'alice'
, NOW()
)
('learn'
, 'bob'
, NOW()
)
('learn'
, 'charlie'
, NOW()
)
Quando a mesma propriedade é repetida várias vezes, o Firestore no modo Datastore pode detectar índices explosivos e sugerir um índice alternativo. No entanto, em todas as outras circunstâncias, como na consulta definida neste exemplo, o banco de dados do modo Datastore gera um índice em explosão. Nesse caso, você pode evitar o índice em explosão configurando manualmente um índice no seu arquivo de configuração de índice.
indexes:
- kind: Task
properties:
- name: tags
- name: created
- kind: Task
properties:
- name: collaborators
- name: created
Isso reduz o número de entradas necessárias para apenas (|tags|
*
|created|
+
|collaborators|
*
|created|)
ou 6 entradas em vez de 9:
('fun'
, NOW()
)
('programming'
, NOW()
)
('learn'
, NOW()
)
('alice'
, NOW()
)
('bob'
, NOW()
)
('charlie'
, NOW()
)
Qualquer operação commit
que faça um índice exceder a entrada do índice ou o limite de tamanho falhará. O texto do erro descreve o limite que foi excedido ("Too many indexed properties"
ou "Index entries too large"
) e o índice personalizado que o causou. Se você criar um novo índice que exceda os limites de qualquer entidade quando criado, as consultas ao índice falharão e o índice aparecerá no estado Error
no console do Google Cloud. Para lidar com índices Error
,
- Remova o índice do arquivo de configuração de índice (
index.yaml
). - Usando a Google Cloud CLI, remova o índice do banco de dados usando o comando
datastore indexes cleanup
, conforme descrito em Como excluir índices não utilizados. - Siga uma das seguintes instruções
- Reformule a definição do índice e as consultas correspondentes
- Remova as entidades que estão fazendo o índice explodir.
- Adicione o índice novamente a
index.yaml
. - Usando a Google Cloud CLI, adicione o índice ao banco de dados executando o comando
datastore indexes create
, conforme descrito em Como atualizar índices.
Você poderá evitar os índices em explosão se não fizer consultas que exijam um índice personalizado usando uma propriedade de lista. Conforme descrito anteriormente, isso inclui consultas com várias ordens de classificação ou com uma combinação de filtros de igualdade e desigualdade.
Índices de projeções
As consultas de projeção exigem que todas as propriedades especificadas na projeção sejam incluídas como um índice. O emulador do Datastore gera automaticamente os índices necessários para você no arquivo de configuração de índice, index.yaml
, que é carregado com seu aplicativo.
Uma forma de reduzir o número de índices necessários é projetar as mesmas propriedades consistentemente, mesmo quando nem todas são necessárias. Por exemplo, essas consultas exigem dois índices separados:
SELECT priority, percent_complete FROM Task
SELECT priority, percent_complete, created FROM Task
No entanto, se você projetar sempre propriedades priority
, percent_complete
, created
, mesmo quando created
não for exigido, somente um índice será necessário.
A conversão de uma consulta em uma projeção talvez exija a criação de um novo índice caso as propriedades dessa projeção não estejam em outra parte da consulta. Por exemplo, suponha que você tenha a seguinte consulta existente:
SELECT * FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete
Ela exige este índice:
indexes:
- kind: Task
properties:
- name: priority
- name: percent_complete
A conversão em uma das consultas de projeção
SELECT created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete
SELECT priority, percent_complete, created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete
introduz uma nova propriedade (created
) e, portanto, será necessário criar um novo índice:
indexes:
- kind: Task
properties:
- name: priority
- name: percent_complete
- name: created
No entanto,
SELECT priority, percent_complete FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete
não altera o índice exigido, uma vez que as propriedades projetadas priority
e percent_complete
já foram incluídas na consulta existente.
Vários bancos de dados
É possível usar gcloud firestore
para gerenciar um único índice para o modo Datastore ou usar gcloud datastore
com um arquivo index.yaml para gerenciar todos os índices em um banco de dados.
gcloud Firestore
gcloud firestore indexes composite create --api-scope=datastore-mode-api --query-scope=QUERY_SCOPE --database=DATABASE_ID
gcloud datastore
gcloud alpha datastore indexes create index.yaml --database=DATABASE_ID
Substitua:
- DATABASE_ID: um ID do banco de dados.
- QUERY_SCOPE:
collection-recursive
para índices ancestrais oucollection-group
para índices não ancestrais.