Nesta página, descrevemos conceitos que serão avaliados ao selecionar os índices do Firestore em modo Datastore para seu aplicativo.
O Firestore no modo Datastore oferece alto desempenho de consulta usando índices para todas as consultas. O desempenho da maioria das consultas depende do tamanho do conjunto de resultados e não do tamanho total do banco de dados.
O Firestore no modo Datastore define índices integrados para cada propriedade em uma entidade. Esses índices de propriedade única são compatíveis com muitas consultas simples. O Firestore no modo Datastore é compatível com um recurso de mesclagem de índices que permite que seu banco de dados mescle índices integrados para aceitar outras consultas. Para consultas mais complexas, defina os índices compostos com antecedência.
Nesta página, o foco é o recurso de mesclagem de índices, porque ele afeta duas oportunidades importantes de otimização de índice:
- Como acelerar consultas
- Como reduzir o número de índices compostos
O exemplo a seguir demonstra o recurso de mesclagem de índices.
Como filtrar entidades Photo
Considere um banco de dados no modo Datastore com entidades do tipo Photo
:
Foto | ||
---|---|---|
Propriedade | Tipo de valor | Descrição |
owner_id |
String | ID do usuário |
tag |
Matriz de strings | Palavras-chave tokenizadas |
size |
Inteiro |
Enumeração:
|
coloration |
Inteiro |
Enumeração:
|
Imagine que você precisa de um recurso de aplicativo que permita aos usuários consultar entidades Photo
com base em um AND
lógico dos seguintes itens:
Até três filtros com base nas propriedades:
owner_id
size
coloration
Uma string de pesquisa
tag
. O aplicativo tokeniza a string de pesquisa em tags e adiciona um filtro para cada tag.Por exemplo, o aplicativo transforma a string de pesquisa
outside, family
nos filtros de consultatag=outside
etag=family
.
Usando índices integrados e o recurso de mesclagem de índices do Firestore em modo Datastore, é
possível atender aos requisitos de índice desse recurso de filtro Photo
sem adicionar
outros índices compostos.
Os índices integrados para entidades Photo
são compatíveis com
consultas de filtro único como:
Python
O recurso de filtro Photo
também exige consultas que combinam vários filtros de igualdade
com um AND
lógico:
Python
O Firestore no modo Datastore pode aceitar essas consultas mesclando índices integrados.
Como mesclar índices
O Firestore no modo Datastore pode usar a mesclagem de índices quando sua consulta e seus índices atendem a todas as seguintes restrições:
- A consulta usa apenas filtros de igualdade (
=
) - Não há índice composto que corresponda perfeitamente aos filtros e à ordem da consulta
- Cada filtro de igualdade corresponde a pelo menos um índice atual com a mesma ordem da consulta
Nessa situação, o Firestore no modo Datastore pode usar índices atuais para aceitar a consulta em vez de exigir que você configure outro índice composto.
Quando dois ou mais índices são classificados pelos mesmos critérios, o Firestore no modo Datastore pode mesclar os resultados de várias verificações de índice para encontrar os resultados comuns a todos esses índices. O Firestore no modo Datastore pode mesclar índices integrados, porque todos eles classificam os valores por chave de entidade.
Mesclando índices integrados, o Firestore no modo Datastore oferece suporte a consultas com filtros de igualdade em várias propriedades:
Python
O Firestore no modo Datastore também pode mesclar resultados de índice de várias seções do mesmo
índice. Mesclando diferentes seções do índice integrado para a propriedade tag
,
o Firestore no modo Datastore é compatível com consultas que combinam vários filtros tag
em um lógico AND
:
Python
As consultas compatíveis com índices integrados mesclados completam o conjunto de consultas
exigido pelo recurso de filtragem Photo
. O suporte ao recurso de filtragem Photo
não exigiu outros índices compostos.
Ao selecionar os índices ideais para seu aplicativo, é importante entender o recurso de mesclagem de índices. A mesclagem de índices oferece ao Firestore no modo Datastore maior flexibilidade de consulta, mas com uma possível compensação pelo desempenho. A próxima seção descreve o desempenho da mesclagem de índices e como melhorar o desempenho adicionando índices compostos.
Como encontrar o índice perfeito
O índice é classificado primeiro pelo ancestral e depois pelos valores da propriedade, na ordem especificada na definição do índice. O índice composto perfeito para uma consulta, que permite uma consulta mais eficiente, é definido nas seguintes propriedades, em ordem:
- Propriedades usadas nos filtros de igualdade
- propriedades usadas em ordens de classificação
- Propriedades usadas no filtro
distinctOn
- Propriedades usadas no intervalo e filtros de desigualdade (que ainda não estão incluídos nas ordens de classificação)
- propriedades usadas em agregações e projeções que ainda não estão incluídas nas ordens de classificação e filtros de intervalo e desigualdade
Isso garante que todos os resultados de cada execução possível da consulta sejam contabilizados. O Firestore em bancos de dados no modo Datastore executa uma consulta usando um índice perfeito seguindo estas etapas:
- Identifica o índice correspondente ao tipo de consulta, às propriedades do filtro, aos operadores do filtro e às ordens de classificação.
- Verifica desde o início do índice até a primeira entidade que atenda a todas ou a um subconjunto das condições do filtro da consulta.
- Continua verificando o índice, retornando cada entidade que satisfaça todas as condições do filtro até
- encontrar uma entidade que não atenda às condições do filtro ou;
- chegar ao fim do índice ou;
- coletar o número máximo de resultados solicitados pela consulta.
Por exemplo, pense na seguinte consulta:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority < 3
ORDER BY priority DESC
O índice composto perfeito para esta consulta é um índice de chaves para entidades do tipo Task
, com colunas para os valores das propriedades category
e priority
. O índice é classificado primeiro em ordem crescente por category
e depois em ordem decrescente por priority
:
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: desc
Duas consultas de formulários iguais, mas com valores de filtro diferentes, usam o mesmo índice. Por exemplo, a consulta a seguir usa o mesmo índice da consulta anterior:
SELECT * FROM Task
WHERE category = 'Work'
AND priority < 5
ORDER BY priority DESC
Para este índice
indexes:
- kind: Task
properties:
- name: category
direction: asc
- name: priority
direction: asc
- name: created
direction: asc
O índice anterior pode atender às duas consultas a seguir:
SELECT * FROM Task
WHERE category = 'Personal'
AND priority = 5
ORDER BY created ASC
do
SELECT * FROM Task
WHERE category = 'Work'
ORDER BY priority ASC, created ASC
Como otimizar sua seleção de índices
Nesta seção, descrevemos as características de desempenho da mesclagem de índices e duas oportunidades de otimização relacionadas à mesclagem de índices:
- Adicione índices compostos para acelerar consultas que dependem de índices mesclados
- Reduzir o número de índices compostos aproveitando os índices mesclados
Desempenho de mesclagem de índices
Em uma mesclagem de índices, o Firestore no modo Datastore mescla com eficiência os índices usando um algoritmo de mesclagem em zigue-zague. Usando esse algoritmo, o modo Datastore une possíveis correspondências de várias verificações de índice para produzir um conjunto de resultados que corresponda a uma consulta. A mesclagem de índices combina os componentes do filtro no tempo de leitura em vez do tempo de gravação. Diferentemente da maioria das consultas do Firestore no modo Datastore em que o desempenho depende apenas do tamanho do conjunto de resultados, o desempenho das consultas de mesclagem de índices depende dos filtros na consulta e de quantas possíveis correspondências o banco de dados considera.
O melhor desempenho de uma mesclagem de índices ocorre quando cada correspondência possível
em um índice satisfaz os filtros de consulta. Nesse caso, o desempenho é O(R * I)
,
em que R
é o tamanho do conjunto de resultados e I
é o número de
índices verificados.
O pior desempenho ocorre quando o banco de dados precisa considerar muitas correspondências
possíveis, mas poucas satisfazem os filtros de consulta. Nesse caso, o
desempenho é O(S)
, em que S
é o tamanho do menor conjunto
de possíveis entidades de uma única verificação de índice.
O desempenho real depende da forma dos dados. O
número médio de entidades consideradas para cada resultado retornado é
O(S/(R * I))
. As consultas têm pior desempenho quando muitas entidades
correspondem a cada verificação de índice, mas poucas entidades correspondem à consulta como
um todo, ou seja, R
é pequeno e S
é grande.
Quatro fatores atenuam esse risco:
O planejador de consultas não procura uma entidade até saber que a entidade corresponde à consulta inteira.
O algoritmo zigue-zague não precisa encontrar todos os resultados para retornar o próximo resultado. Se você solicitar os 10 primeiros resultados, pagará apenas a latência para encontrar esses 10 resultados.
O algoritmo zigue-zague pula seções grandes de resultados falsos positivos. O pior desempenho ocorrerá somente se resultados positivos falsos estiverem perfeitamente entrelaçados (em ordem de classificação) entre verificações.
A latência depende do número de entidades encontradas em cada verificação de índice, não do número de entidades que correspondem a cada filtro. Como mostrado na próxima seção, adicione índices compostos para melhorar o desempenho da mesclagem de índices.
Como acelerar uma consulta de mesclagem de índices
Quando o Firestore no modo Datastore mescla índices, cada verificação de índice geralmente é mapeada para um único filtro na consulta. É possível melhorar o desempenho da consulta adicionando índices compostos que correspondem a vários filtros na consulta.
Considere esta consulta:
Python
Cada filtro mapeia para uma verificação de índice nos seguintes índices integrados:
Index(Photo, owner_id) Index(Photo, size) Index(Photo, tag)
Ao adicionar o índice composto Index(Photo, owner_id, size)
, a consulta
é mapeada para duas verificações de índice em vez de três:
# Satisfies both 'owner_id=username' and 'size=2'
Index(Photo, owner_id, size)
Index(Photo, tag)
Considere um cenário com muitas imagens grandes, muitas imagens em preto e branco, mas poucas imagens panorâmicas grandes. Uma filtragem de consulta para imagens panorâmicas e em preto e branco será lenta se mesclar índices integrados:
Python
Para melhorar o desempenho da consulta, é possível diminuir o valor de S
(menor
conjunto de entidades em uma única verificação de índice) em
O(S/(R * I))
adicionando o seguinte índice composto:
Index(Photo, size, coloration)
Em comparação com o uso de dois índices integrados, esse índice composto produz menos resultados em potencial para os mesmos dois filtros de consulta. Essa abordagem melhora substancialmente o desempenho ao custo de mais um índice.
Como reduzir o número de índices compostos com mesclagem de índices
Embora os índices compostos que correspondem exatamente aos filtros em uma consulta tenham melhor desempenho, nem sempre é melhor ou possível adicionar um índice composto para cada combinação de filtros. É necessário equilibrar seus índices compostos em relação aos seguintes itens:
Limites de índice composto:
Limite Valor Número máximo de índices compostos de um projeto -
200 quando você não tiver ativado o faturamento do projeto do Google Cloud.
Se você precisar de mais cota, ative o faturamento do projeto do Google Cloud.
-
500 quando você ativar o faturamento do projeto do Google Cloud.
Entre em contato com o suporte para solicitar uma aumentar a esse limite.
Soma máxima dos tamanhos das entradas do índice composto de uma entidade 2 MiB Soma máxima dos itens a seguir para uma entidade: - número de valores de propriedade indexados
- número de entradas de índice composto
20.000 -
- Custos de armazenamento de cada novo índice.
- Efeitos na latência de gravação.
Os problemas de indexação geralmente surgem com campos de vários valores,
como a propriedade tag
das entidades Photo
.
Por exemplo, imagine que o recurso de filtragem Photo
agora precisa oferecer
suporte a cláusulas de ordem decrescente com base em quatro outras propriedades:
Foto | ||
---|---|---|
Propriedade | Tipo de valor | Descrição |
date_added |
Inteiro | Data/hora |
rating |
Ponto flutuante | Avaliação de usuários agregados |
comment_count |
Inteiro | Número de comentários |
download_count |
Inteiro | Número de downloads |
Se você desconsiderar o campo tag
, é possível selecionar
índices compostos que correspondam a cada combinação de filtros Photo
:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -comments) Index(Photo, size, -date_added) Index(Photo, size, -comments) ... Index(Photo, owner_id, size, -date_added) Index(Photo, owner_id, size, -comments) ... Index(Photo, owner_id, size, coloration, -date_added) Index(Photo, owner_id, size, coloration, -comments)
O número total de índices compostos é:
2^(number of filters) * (number of different orders) = 2 ^ 3 * 4 = 32 composite indexes
Se você tentar aceitar até três filtros tag
, o número total de índices
compostos será:
2 ^ (3 + 3 tag filters) * 4 = 256 indexes.
Índices que incluem propriedades de vários valores, como
tag
, também levam a
problemas de índice em explosão que
aumentam os custos de armazenamento e a latência de gravação.
Para oferecer suporte a filtros no campo tag
desse recurso, é possível reduzir o número
total de índices contando com os índices mesclados. O seguinte conjunto de índices
compostos é o mínimo necessário para oferecer suporte ao recurso de filtragem Photo
com
ordenação:
Index(Photo, owner_id, -date_added) Index(Photo, owner_id, -rating) Index(Photo, owner_id, -comments) Index(Photo, owner_id, -downloads) Index(Photo, size, -date_added) Index(Photo, size, -rating) Index(Photo, size, -comments) Index(Photo, size, -downloads) ... Index(Photo, tag, -date_added) Index(Photo, tag, -rating) Index(Photo, tag, -comments) Index(Photo, tag, -downloads)
O número de índices compostos definidos é:
(number of filters + 1) * (number of orders) = 7 * 4 = 28
A mesclagem de índices também oferece os seguintes benefícios:
- Permite que uma entidade
Photo
ofereça suporte a até 1.000 tags sem limite no número detag
filtros por consulta. - Reduz o número total de índices, o que reduz os custos de armazenamento e a latência de gravação.
Como selecionar índices para seu aplicativo
Selecione índices ideais para seu banco de dados no modo Datastore usando duas abordagens:
Usar a mesclagem de índices para compatibilidade com outras consultas
- Requer menos índices compostos.
- Reduz o custo de armazenamento por entidade.
- Melhora a latência de gravação
- Evita índices em explosão.
- O desempenho depende da forma dos dados.
Definir um índice composto que corresponda a vários filtros em uma consulta
- Melhora o desempenho da consulta.
- Desempenho de consulta consistente que não depende da forma dos dados.
- Precisa permanecer abaixo do limite de índices compostos
- Aumento no custo de armazenamento por entidade.
- Maior latência de gravação
Ao descobrir os índices ideais para seu aplicativo, a resposta pode mudar conforme a forma dos dados é alterada. O desempenho da consulta de amostragem fornece uma boa ideia das consultas comuns do seu aplicativo e de suas consultas lentas. Com essas informações, é possível adicionar índices para melhorar o desempenho de consultas comuns e lentas.