Todas as consultas do Firestore no modo Datastore calculam os respetivos resultados através de um ou mais índices que contêm chaves de entidades numa sequência especificada pelas propriedades do índice e, opcionalmente, os antepassados da entidade. Os índices são atualizados para refletir quaisquer alterações que a aplicação faça às respetivas entidades, para que os resultados corretos de todas as consultas estejam disponíveis sem necessidade de cálculos adicionais.
Existem dois tipos de índices:
- Índices incorporados
- Por predefinição, uma base de dados do modo Datastore predefine automaticamente um índice para cada propriedade de cada tipo de entidade. Estes índices de propriedades únicas são adequados para tipos simples de consultas.
- Índices compostos
- Os índices compostos indexam vários valores de propriedades por entidade indexada. Os índices compostos suportam consultas complexas e são definidos num ficheiro de configuração de índice (
index.yaml
).
Os tipos de índices são abordados mais detalhadamente mais adiante.
Definição e estrutura do índice
É definido um índice numa lista de propriedades de um determinado tipo de entidade, com uma ordem correspondente (ascendente ou descendente) para cada propriedade. Para utilização com consultas de antepassados, o índice também pode incluir opcionalmente os antepassados de uma entidade.
Um índice contém entradas para todas as propriedades com nome na definição do índice. Cada entrada do índice representa uma entidade que é um resultado potencial para consultas baseadas no índice. Uma entidade só é incluída no índice se tiver 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 um valor, essa entidade não aparece no índice e, por isso, nunca é devolvida como resultado para qualquer consulta baseada no índice.
O índice composto é ordenado primeiro pelo antepassado e, em seguida, pelos valores das propriedades, na ordem especificada na definição do índice. Com base nesta compreensão, pode criar o índice perfeito que permite consultas eficientes.
Configuração do índice
O Firestore no modo Datastore fornece índices incorporados ou automáticos para consultas dos seguintes formulários:
- Consultas sem tipo que usam apenas filtros de chave e antepassado
- Consultas que usam apenas filtros de igualdade e antecessores
- Consultas que usam apenas filtros de desigualdade (limitados a uma única propriedade)
- Consultas que usam apenas filtros de antepassados, filtros de igualdade em propriedades e filtros de desigualdade em chaves
- Consultas sem filtros e apenas uma ordem de ordenação numa propriedade, ascendente ou descendente
Por exemplo, por predefinição, as bases de dados do modo Datastore predefinem automaticamente dois índices de propriedade única para cada propriedade de cada tipo de entidade, um por ordem ascendente e outro por ordem descendente. Se não quiser que a sua base de dados mantenha um índice para uma propriedade, exclua a propriedade dos seus índices. Tenha em atenção que a exclusão de uma propriedade remove-a de todos os índices compostos.
Os índices incorporados são suficientes para executar muitas consultas simples, como consultas apenas de igualdade e consultas de desigualdade simples.
Os índices incorporados não aparecem na página Índices da Google Cloud consola.
Para consultas mais complexas, uma aplicação tem de definir índices compostos ou manuais. Os índices compostos são obrigatórios para consultas do seguinte formato:
- Consultas com filtros de desigualdade e antecessores
- Consultas com um ou mais filtros de desigualdade numa propriedade e um ou mais filtros de igualdade noutras propriedades
- Consultas com uma ordem de ordenação nas chaves por ordem descendente
- Consultas com várias ordens de ordenação
- Consultas com um ou mais filtros e uma ou mais ordens de ordenação
Os índices compostos são definidos no ficheiro de configuração de índice da aplicação (index.yaml
). (Os índices incorporados não estão contidos no ficheiro de configuração de índice.)
Os índices compostos são compostos por várias propriedades e requerem que cada propriedade individual não seja excluída dos seus índices.
Os índices compostos são visíveis na página Índices da Google Cloud consola. Não pode usar a consola Google Cloud para criar ou atualizar índices compostos.
Se a aplicação tentar executar uma consulta que não pode ser executada com os índices disponíveis (incorporados ou especificados no ficheiro de configuração do índice), a consulta falha.
A API do modo Datastore sugere automaticamente índices adequados para a maioria das aplicações. Consoante a utilização da base de dados do modo Datastore pela sua aplicação, bem como o tamanho e o formato dos seus dados, podem ser justificadas as alterações manuais aos seus índices. Por exemplo, escrever entidades com vários valores de propriedades pode resultar num índice em expansão com custos de armazenamento elevados e uma latência de escrita aumentada.
O emulador do Datastore pode ajudar a facilitar a gestão do ficheiro de configuração do índice. Em vez de não executar uma consulta que requer um índice e não tem nenhum, o emulador do armazenamento de dados pode gerar uma configuração de índice que permitiria que a consulta fosse bem-sucedida. Se o teste local de uma aplicação exercitar todas as consultas possíveis que a aplicação vai emitir, usando todas as combinações de filtro e ordem de ordenação, as entradas geradas representam um conjunto completo de índices. Se os seus testes não exercitarem todos os formulários de consulta possíveis, pode rever e ajustar o ficheiro de configuração do índice antes de atualizar os índices.
Pode saber mais acerca da index.yaml
em Configuração do índice.
Implementar ou eliminar índices
Quando terminar de modificar o ficheiro de configuração do índice, execute o comando gcloud datastore indexes create
para colocar os índices em serviço.
Saiba como atualizar os seus índices.
Se implementou anteriormente índices que já não são necessários, pode eliminar os índices não usados.
Custos de armazenamento e latência de escrita
Os índices contribuem para os seus custos de armazenamento. O tamanho da entrada do índice descreve a forma como os índices incorporados e compostos contribuem para o tamanho do armazenamento da sua base de dados. Pode usar as estatísticas do Firestore no modo Datastore para ver mais informações sobre as entradas de índice e o tamanho do armazenamento de índice.
Os índices também contribuem para a latência de escrita. Quando atualiza um valor de propriedade, a base de dados também atualiza todos os índices relacionados. Quanto mais índices a base de dados tiver de atualizar, mais tempo demora a operação.
Pode reduzir os custos de armazenamento e melhorar o desempenho de escrita eliminando índices não usados e excluindo propriedades da indexação. Isto também impede que as operações falhem devido a limites de índice.
Índices e propriedades
Seguem-se algumas considerações especiais a ter em atenção acerca dos índices e da respetiva relação com as propriedades das suas entidades:
Propriedades com tipos de valores mistos
Quando duas entidades têm propriedades com o mesmo nome, mas tipos de valores diferentes, um índice da propriedade ordena as entidades primeiro por tipo de valor e, em seguida, por uma ordenação secundária adequada a cada tipo. Por exemplo, se duas entidades tiverem cada uma uma propriedade denominada age
, uma com um valor inteiro e outra com um valor de string, a entidade com o valor inteiro precede sempre a entidade com o valor de string quando ordenadas pela propriedade age
, independentemente dos valores das propriedades.
Isto é especialmente importante no caso de números inteiros e de vírgula flutuante, que são tratados como tipos separados pelo modo Datastore. Uma vez que todos os números inteiros são ordenados antes de todos os números de vírgula flutuante, uma propriedade com o valor inteiro 38
é ordenada antes de uma com o valor de vírgula flutuante 37.5
.
Propriedades excluídas
Se souber que nunca vai ter de filtrar nem ordenar por uma determinada propriedade, pode indicar à base de dados do modo Datastore que não mantenha entradas de índice para essa propriedade, excluindo-a dos índices. Isto reduz o custo de execução da sua aplicação, diminuindo o tamanho de armazenamento necessário para as entradas de índice. Isto também pode melhorar a latência de escrita. Uma entidade com uma propriedade excluída comporta-se como se a propriedade não estivesse definida: as consultas com um filtro ou uma ordem de ordenação na propriedade excluída nunca correspondem a essa entidade.
A propriedade description
no exemplo seguinte é excluída dos índices:
C#
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Go
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Java
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Node.js
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
PHP
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Python
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Ruby
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
GQL
Não aplicávelA consulta no exemplo seguinte não devolve resultados se a propriedade description
tiver sido excluída:
C#
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Go
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Java
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Node.js
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
PHP
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Python
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Ruby
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
GQL
# Will not return any results! SELECT * FROM Task WHERE description = 'A task description.'
Pode alterar posteriormente a propriedade novamente para indexada.
No entanto, tenha em atenção que a alteração de uma propriedade de excluída para indexada não afeta as entidades existentes que possam ter sido criadas antes da alteração. As consultas que filtram a propriedade não devolvem essas entidades existentes, porque as entidades não foram escritas no índice da consulta quando foram criadas. Para tornar as entidades acessíveis por consultas futuras, tem de as reescrever na sua base de dados para que sejam introduzidas nos índices adequados. Ou seja, tem de fazer o seguinte para cada entidade existente:
- Procurar (obter) a entidade.
- Escrever (colocar) a entidade novamente na sua base de dados.
Da mesma forma, a alteração de uma propriedade de indexada para excluída só afeta as entidades escritas posteriormente na base de dados. As entradas de índice de quaisquer entidades existentes com essa propriedade continuam a existir até as entidades serem atualizadas ou eliminadas. Para evitar resultados indesejados, tem de limpar o seu código de todas as consultas que filtram ou ordenam pela propriedade (agora excluída).
Limites de índice
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. Estes limites são elevados e a maioria das aplicações não é afetada. No entanto, existem circunstâncias em que pode encontrar os limites.
Conforme descrito acima, uma base de dados do modo Datastore cria uma entrada num índice predefinido para cada propriedade de cada entidade, exceto as que declarou explicitamente como excluídas dos seus índices. A propriedade também pode ser incluída em índices personalizados adicionais declarados no seu ficheiro de configuração de índice (index.yaml
). Desde que uma entidade não tenha propriedades de lista, terá, no máximo, uma entrada em cada índice personalizado (para índices não antecessores) ou uma para cada um dos antecessores da entidade (para índices de antecessores). Cada uma destas entradas de índice tem de ser atualizada sempre que o valor da propriedade muda.
Para uma propriedade que tem um único valor para cada entidade, cada valor possível tem de ser armazenado apenas uma vez por entidade no índice predefinido da propriedade. Mesmo assim, é possível que uma entidade com um grande número de propriedades de valor único exceda a entrada de índice ou o limite de tamanho. Da mesma forma, uma entidade que pode ter vários valores para a mesma propriedade requer uma entrada de índice separada para cada valor. Mais uma vez, se o número de valores possíveis for elevado, essa entidade pode exceder o limite de entradas.
A situação agrava-se no caso de entidades com várias propriedades, cada uma das quais pode assumir vários valores. Para acomodar essa entidade, o índice tem de incluir uma entrada para todas as combinações possíveis de valores de propriedades. Os índices personalizados que se referem a várias propriedades, cada uma com vários valores, podem "explodir" de forma combinatória, o que requer um grande número de entradas para uma entidade com apenas um número relativamente pequeno de valores de propriedades possíveis. Estes índices em expansão podem aumentar drasticamente o tamanho de armazenamento de uma entidade devido ao grande número de entradas de índice que têm de ser armazenadas. A expansão dos índices também pode fazer com que a entidade exceda a contagem de entradas de índice ou o limite de tamanho.
Considere o seguinte código:
C#
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Go
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Java
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Node.js
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
PHP
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Python
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Ruby
Para saber como instalar e usar a biblioteca cliente do Cloud Datastore, consulte as bibliotecas cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby Cloud Datastore.
Para se autenticar no Cloud Datastore, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
GQL
Não aplicávelCria uma entidade Task
com três valores para a propriedade tags
, três valores para a propriedade collaborators
e created
definida para a data atual. Isto requer 9 entradas de índice, uma para cada combinação possível de valores de propriedades:
('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 detetar índices em expansão e sugerir um índice alternativo. No entanto, em todas as outras circunstâncias (como a consulta definida neste exemplo), uma base de dados do modo Datastore gera um índice em expansão. Neste caso, pode contornar o índice em expansão configurando manualmente um índice no ficheiro de configuração do índice:
indexes:
- kind: Task
properties:
- name: tags
- name: created
- kind: Task
properties:
- name: collaborators
- name: created
Isto 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 com que um índice exceda o limite de entradas ou de tamanho do índice falha. O texto do erro descreve que limite foi excedido ("Too many indexed properties"
ou "Index entries too large"
) e que índice personalizado foi a causa. Se criar um novo índice que exceda os limites de qualquer entidade quando for criado, as consultas ao índice falham e o índice aparece no estado Error
na Google Cloud consola. Para processar esses índices Error
,
- Remova o índice do ficheiro de configuração do índice (
index.yaml
). - Usando a CLI do Google Cloud, remova o índice da base de dados com o comando
datastore indexes cleanup
, conforme descrito no artigo Eliminar índices não usados. - Uma das seguintes situações:
- Reformular a definição do índice e as consultas correspondentes ou
- Remova as entidades que estão a causar a explosão do índice.
- Adicione novamente o índice a
index.yaml
. - Usando a CLI do Google Cloud, adicione o índice à base de dados executando o comando
datastore indexes create
, conforme descrito em Atualizar índices.
Pode evitar a expansão excessiva dos índices evitando consultas que exijam um índice personalizado com uma propriedade de lista. Conforme descrito anteriormente, isto inclui consultas com várias ordens de ordenação ou consultas com uma combinação de filtros de igualdade e desigualdade.
Índices para projeções
As consultas de projeção requerem que todas as propriedades especificadas na projeção sejam incluídas num índice. O emulador do Datastore gera automaticamente os índices necessários para si no ficheiro de configuração do índice, index.yaml
, que é carregado com a sua aplicação.
Uma forma de minimizar o número de índices necessários é projetar as mesmas propriedades de forma consistente, mesmo quando nem todas são sempre necessárias. Por exemplo, estas consultas requerem dois índices separados:
SELECT priority, percent_complete FROM Task
SELECT priority, percent_complete, created FROM Task
No entanto, se projetar sempre as propriedades priority
, percent_complete
e created
, mesmo quando created
não é necessário, só precisa de um índice.
A conversão de uma consulta existente numa consulta de projeção pode exigir a criação de um novo índice se as propriedades na projeção ainda não estiverem incluídas noutra parte da consulta. Por exemplo, suponha que tinha uma consulta existente como
SELECT * FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete
que requer o índice:
indexes:
- kind: Task
properties:
- name: priority
- name: percent_complete
Converter isto numa 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, por isso, vai exigir a criação de 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 alteraria o índice necessário, uma vez que as propriedades projetadas priority
e percent_complete
já estavam incluídas na consulta existente.
Várias bases de dados
Pode usar gcloud firestore
para gerir um único índice para o modo Datastore ou usar gcloud datastore
com um ficheiro index.yaml para gerir todos os índices numa base 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 o seguinte:
- DATABASE_ID: um ID da base de dados.
- QUERY_SCOPE:
collection-recursive
para índices de predecessores oucollection-group
para índices não predecessores.