Este documento descreve como consultar gráficos de propriedades no Spanner Graph. Os exemplos nesta secção usam o esquema de grafos que cria em Configure e consulte o Spanner Graph, que é ilustrado no seguinte diagrama:
Execute uma consulta do Spanner Graph
Pode executar consultas de grafos do Spanner das seguintes formas:
A Google Cloud consola
Envie uma consulta na página Spanner Studio. Para aceder à página do Spanner Studio, clique em Spanner Studio na página Vista geral da base de dados ou na página Vista geral da tabela. Para mais informações sobre como aceder ao Spanner Studio, consulte o artigo Faça a gestão dos seus dados através da Google Cloud consola.
A ferramenta de linha de comandos
gcloud spanner
Envie um comando através do comando
gcloud spanner databases execute-sql
.A API REST
executeSql
eexecuteStreamingSql
A API RPC
ExecuteSql
eExecuteStreamingSql
Visualize os resultados da consulta do Spanner Graph
Pode visualizar os resultados da consulta do Spanner Graph no Spanner Studio se a consulta devolver nós completos no formato JSON. Para mais informações, consulte Trabalhe com visualizações de gráficos do Spanner.
Estrutura de consulta do Spanner Graph
Esta secção descreve detalhadamente cada componente de consulta.
O exemplo seguinte ilustra a estrutura básica de uma consulta do Spanner Graph.
O Spanner Graph permite-lhe criar vários gráficos numa base de dados. A consulta começa por especificar o gráfico de destino, FinGraph
, através da cláusula GRAPH
.
Correspondência de padrões de grafos
A correspondência de padrões de grafos encontra padrões específicos no seu grafo. Os padrões mais básicos são os padrões de elementos (padrões de nós e padrões de arestas), que correspondem a elementos de grafos (nós e arestas, respetivamente). Os padrões de elementos podem ser compostos em padrões de caminhos e padrões mais complexos.
Padrões de nós
Um padrão de nó é um padrão que corresponde a nós do seu gráfico. Este padrão compreende um par de parênteses correspondente, que pode conter opcionalmente uma variável de padrão de gráfico, uma expressão de etiqueta e filtros de propriedades.
Encontre todos os nós
A seguinte consulta devolve todos os nós no gráfico. A variável n
, denominada variável de padrão de gráfico, é associada aos nós correspondentes. Neste caso, o padrão de nó corresponde a todos os nós no gráfico.
GRAPH FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;
Resultado
A consulta devolve label
e id
da seguinte forma:
etiqueta | id |
---|---|
Conta | 7 |
Conta | 16 |
Conta | 20 |
Pessoa | 1 |
Pessoa | 2 |
Pessoa | 3 |
Encontre todos os nós com uma etiqueta específica
A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person
label.
A consulta devolve as propriedades label
e id
, name
dos nós com correspondência.
GRAPH FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;
Resultado
etiqueta | id | nome |
---|---|---|
Pessoa | 1 | Alex |
Pessoa | 2 | Dana |
Pessoa | 3 | Lee |
Encontre todos os nós que correspondem a uma expressão de etiqueta
Pode criar uma expressão de etiqueta com um ou mais operadores lógicos.
A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person
ou Account
. O conjunto de propriedades expostas pela variável de padrão de gráfico n
é o superconjunto das propriedades expostas pelos nós que têm a etiqueta Person
ou Account
.
GRAPH FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;
- Nos resultados, todos os nós têm a propriedade
id
. - Os nós correspondentes à etiqueta
Account
têm a propriedadecreate_time
, mas não têm a propriedadebirthday
. É devolvido umNULL
para a propriedadebirthday
para esses nós. - Os nós correspondentes à etiqueta
Person
têm a propriedadebirthday
, mas não têm a propriedadecreate_time
. É devolvido umNULL
para a propriedadecreate_time
para esses nós.
Resultado
etiqueta | id | aniversário | create_time |
---|---|---|---|
Conta | 7 | NULL | 2020-01-10T14:22:20.222Z |
Conta | 16 | NULL | 2020-01-28T01:55:09.206Z |
Conta | 20 | NULL | 2020-02-18T13:44:20.655Z |
Pessoa | 1 | 1991-12-21T08:00:00Z | NULL |
Pessoa | 2 | 1980-10-31T08:00:00Z | NULL |
Pessoa | 3 | 1986-12-07T08:00:00Z | NULL |
Para mais informações sobre as regras de expressão de etiquetas, consulte o artigo Expressão de etiquetas.
Encontre todos os nós que correspondem à expressão de etiqueta e ao filtro de propriedades
A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person
e onde a propriedade id
é igual a 1
.
GRAPH FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;
Resultado
etiqueta | id | nome | aniversário |
---|---|---|---|
Pessoa | 1 | Alex | 1991-12-21T08:00:00Z |
Pode usar a cláusula WHERE
para formar condições de filtragem mais complexas em etiquetas e propriedades.
A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person
e a propriedade birthday
é anterior a 1990-01-10
.
GRAPH FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;
Resultado
etiqueta | nome | aniversário |
---|---|---|
Pessoa | Dana | 1980-10-31T08:00:00Z |
Pessoa | Lee | 1986-12-07T08:00:00Z |
Padrões de limites
Um padrão de aresta corresponde a arestas ou relações entre nós. Os padrões de arestas estão
entre parênteses retos []
com os símbolos -
, ->
ou <-
para indicar
direções.
Semelhantes aos padrões de nós, as variáveis de padrão de grafos são usadas para associar a elementos de arestas correspondentes.
Encontre todas as arestas com etiquetas correspondentes
A consulta seguinte devolve todas as arestas no gráfico que têm a etiqueta Transfers
.
A variável de padrão de gráfico e
está associada às arestas correspondentes.
GRAPH FinGraph
MATCH -[e:Transfers]->
RETURN e.Id as src_account, e.order_number
Resultado
src_account | order_number |
---|---|
7 | 304330008004315 |
7 | 304120005529714 |
16 | 103650009791820 |
20 | 304120005529714 |
20 | 302290001255747 |
Encontrar todas as arestas que correspondem à expressão de etiqueta e ao filtro de propriedades
Semelhante a um padrão de nó, um padrão de aresta pode usar expressões de etiqueta, especificação de propriedade e cláusulas WHERE
, como mostrado na consulta seguinte. A consulta
encontra todas as arestas etiquetadas com Transfers
que correspondem a um order_number
especificado.
GRAPH FinGraph
MATCH -[e:Transfers {order_number: "304120005529714"}]->
RETURN e.Id AS src_account, e.order_number
Resultado
src_account | order_number |
---|---|
7 | 304120005529714 |
20 | 304120005529714 |
Encontre todas as arestas usando qualquer padrão de arestas de direção
Embora todas as arestas no gráfico do Spanner sejam direcionadas, pode usar o any
direction
padrão de arestas -[]-
numa consulta para corresponder a arestas em qualquer direção.
A seguinte consulta encontra todas as transferências que envolvem uma conta bloqueada.
GRAPH FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account {is_blocked:true})
RETURN transfer.order_number, transfer.amount;
Resultado
order_number | valor |
---|---|
304330008004315 | 300 |
304120005529714 | 100 |
103650009791820 | 300 |
302290001255747 | 200 |
Padrões de caminho
Um padrão de caminho é criado a partir de padrões de nós e arestas alternados.
Encontrar todos os caminhos a partir de um nó com filtros de etiquetas e propriedades especificados, usando um padrão de caminho
A seguinte consulta encontra todas as transferências para uma conta iniciadas a partir de uma conta pertencente a Person
com id
igual a 2
.
Cada resultado com correspondência representa um caminho de Person
{id: 2}
através de um Account
ligado usando a aresta Owns
, para outro Account
usando a aresta Transfers
.
GRAPH FinGraph
MATCH
(p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
(to_account:Account)
RETURN
p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;
Resultado
sender_id | from_id | to_id |
---|---|---|
2 | 20 | 7 |
2 | 20 | 16 |
Padrões de caminhos quantificados
Um padrão quantificado permite que um padrão seja repetido dentro de um intervalo especificado.
Faça corresponder um padrão de contorno quantificado
A seguinte consulta encontra todas as contas de destino que estão a um a três transferências de distância de uma origem Account
com id
igual a 7
, exceto a própria origem.
O padrão de limite com o quantificador {1, 3}
.
GRAPH FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;
Resultado
src_account_id | path_length | dst_account_id |
---|---|---|
7 | 1 | 16 |
7 | 1 | 16 |
7 | 1 | 16 |
7 | 3 | 16 |
7 | 3 | 16 |
7 | 2 | 20 |
7 | 2 | 20 |
O exemplo anterior usa a função ARRAY_LENGTH
para aceder ao
group variable
e
. Para mais informações, consulte a
variável do grupo de acesso.
Algumas linhas nos resultados de exemplo são repetidas porque podem existir vários caminhos entre o mesmo par de contas src
e dst
que correspondem ao padrão.
Faça corresponder um padrão de caminho quantificado
A consulta seguinte encontra caminhos entre nós Account
com um a dois Transfers
limites através de contas intermédias que estão bloqueadas.
O padrão do caminho entre parênteses é quantificado e a cláusula WHERE
é usada nos parênteses para especificar condições para o padrão repetido.
GRAPH FinGraph
MATCH
(src:Account)
((a:Account)-[:Transfers]->(b:Account {is_blocked:true}) WHERE a != b){1,2}
-[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;
Resultado
src_account_id | dst_account_id |
---|---|
7 | 20 |
7 | 20 |
20 | 20 |
Variáveis de grupo
Uma variável de padrão de gráfico declarada num padrão quantificado é considerada uma variável de grupo quando acedida fora do padrão quantificado e é associada a uma matriz de elementos do gráfico correspondentes.
Pode aceder a uma variável de grupo como uma matriz em que os elementos do gráfico são preservados pela ordem de apresentação ao longo dos caminhos correspondentes. Pode agregar uma variável de grupo usando a agregação horizontal.
Variável do grupo de acesso
No exemplo seguinte, a variável e
é acedida da seguinte forma:
- Uma variável de padrão de gráfico associada a uma única aresta na cláusula
WHERE
e.amount > 100
(no padrão quantificado). - Uma variável de grupo associada a uma matriz de elementos de aresta em
ARRAY_LENGTH(e)
na declaraçãoRETURN
(fora do padrão quantificado). - Uma variável de grupo associada a uma matriz de elementos de aresta, que é agregada por
SUM(e.amount)
fora do padrão quantificado. Este é um exemplo de agregação horizontal.
GRAPH FinGraph
MATCH
(src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
(dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
total_amount, dst.id AS dst_account_id;
Resultado
src_account_id | path_length | total_amount | dst_account_id |
---|---|---|---|
7 | 1 | 300 | 16 |
7 | 2 | 600 | 20 |
Quaisquer caminhos e caminhos mais curtos
Para limitar os caminhos correspondentes em cada grupo de caminhos que partilham os mesmos nós de origem e destino, pode usar o ANY
ou o ANY SHORTEST
prefixo de pesquisa do caminho.
Só pode aplicar estes prefixos antes de um padrão de caminho completo e não os pode aplicar entre parênteses.
Corresponda usando QUALQUER
A seguinte consulta encontra todas as contas únicas acessíveis que estão a um ou dois níveis de distância de um determinado nó Account
.Transfers
O prefixo de pesquisa de caminho ANY
garante que apenas é devolvido um caminho entre um par único de nós src
e dst
Account
. No exemplo seguinte, embora possa alcançar o nó Account
com {id: 16}
em dois caminhos diferentes a partir do nó Account
de origem, os resultados incluem apenas um caminho.
GRAPH FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY_CONCAT(ARRAY_AGG(e.Id), [dst.Id])
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;
Resultado
src_account_id | dst_account_id | ids_in_path |
---|---|---|
7 | 16 | 7,16 |
7 | 20 | 7,16,20 |
Padrões de gráficos
Um padrão de gráfico consiste num ou mais padrões de caminho, separados por vírgula (,
).
Os padrões de gráfico podem conter uma cláusula WHERE
, que lhe permite aceder a todas as variáveis de padrão de gráfico nos padrões de caminho para formar condições de filtragem. Cada padrão de caminho gera uma coleção de caminhos.
Encontre correspondências através de um padrão de gráfico
A seguinte consulta identifica contas de intermediários e os respetivos proprietários envolvidos em valores de transações superiores a 200, através dos quais os fundos são transferidos de uma conta de origem para uma conta bloqueada.
Os seguintes padrões de caminho formam o padrão de gráfico:
- O primeiro padrão encontra caminhos em que a transferência ocorre de uma conta para uma conta bloqueada através de uma conta intermédia.
- O segundo padrão encontra caminhos de uma conta para a pessoa proprietária.
A variável interm
funciona como uma ligação comum entre os dois padrões de caminho, o que
requer que interm
faça referência ao mesmo nó de elemento em ambos os padrões de caminho. Isto
cria uma operação de junção igual com base na variável interm
.
GRAPH FinGraph
MATCH
(src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
(interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
src.id AS src_account_id, dst.id AS dst_account_id,
interm.id AS interm_account_id, p.id AS owner_id;
Resultado
src_account_id | dst_account_id | interm_account_id | owner_id |
---|---|---|---|
20 | 16 | 7 | 1 |
Instruções de consulta lineares
Pode encadear várias declarações de grafos para formar uma declaração de consulta linear. As declarações são executadas pela mesma ordem em que aparecem na consulta.
- Cada declaração usa o resultado da declaração anterior como entrada. A entrada está vazia para a primeira declaração.
- O resultado da última declaração é o resultado final.
Encontre a transferência máxima para uma conta bloqueada
A seguinte consulta encontra a conta e o respetivo proprietário com a maior transferência de saída para uma conta bloqueada.
GRAPH FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account {is_blocked:true})
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;
A tabela seguinte ilustra como os resultados intermédios são transmitidos nas declarações. Apenas são apresentadas algumas propriedades dos resultados intermédios, por brevidade.
Extracto | Resultado intermédio (abreviado) | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MATCH (src_account:Account) -[transfer:Transfers]-> (dst_account:Account {is_blocked:true}) |
|
||||||||||||
ORDER BY transfer.amount DESC |
|
||||||||||||
LIMIT 1 |
|
||||||||||||
MATCH (src_account:Account) <-[owns:Owns]- (owner:Person) |
|
||||||||||||
RETURN src_account.id AS account_id, owner.name AS owner_name |
|
Resultado
account_id | owner_name |
---|---|
7 | Alex |
Instrução return
A instrução return define o que devolver dos padrões correspondentes. Pode aceder a variáveis de padrão de gráfico, conter expressões e outras cláusulas, como ORDER_BY e GROUP_BY. Consulte o
RETURN
extrato.
O Spanner Graph não suporta a devolução de elementos do gráfico como resultados da consulta. Para devolver o elemento do gráfico completo, use a função TO_JSON
ou a função SAFE_TO_JSON
.
Destas duas funções, recomendamos que use SAFE_TO_JSON
.
Devolver elementos do gráfico como JSON
GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;
GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Certain fields in the graph elements, such as TOKENLIST, can't be returned
-- in the TO_JSON function. In those cases, use the SAFE_TO_JSON function instead.
RETURN SAFE_TO_JSON(n) AS n;
Resultado
n |
---|
{"identifier":"mUZpbkdyYXBoLkFjY291bnQAeJEO","kind":"node","labels":["Account"],"properties":{"create_time":"2020-01-10T14:22:20.222Z","id":7,"is_blocked":false,"nick_name":"Vacation Fund"}} |
Compor consultas maiores com a palavra-chave NEXT
Pode encadear várias declarações de consulta linear de gráficos usando a palavra-chave NEXT
. A entrada para a primeira declaração de consulta linear está vazia. O resultado de cada declaração de consulta linear torna-se entrada para a declaração de consulta linear seguinte.
O exemplo seguinte encontra o proprietário da conta com o maior número de transferências recebidas
encadeando várias declarações lineares de gráficos. Tenha em atenção que pode usar a mesma variável, account
neste exemplo, para se referir ao mesmo elemento do gráfico em várias declarações lineares.
GRAPH FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1
NEXT
MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;
Resultado
account_id | owner_name | num_incoming_transfers |
---|---|---|
16 | Lee | 3 |
Funções e expressões
Pode usar todas as funções do GoogleSQL (funções agregadas e escalares), operadores e expressões condicionais na consulta de gráficos do Spanner. O Spanner Graph também suporta funções e operadores específicos de gráficos.
Funções e operadores incorporados
As seguintes funções e operadores são usadas com frequência no GQL:
PROPERTY_EXISTS(n, birthday)
: devolve sen
expõe a propriedadebirthday
.LABELS(n)
: devolve as etiquetas den
, conforme definido no esquema do gráfico.PROPERTY_NAMES(n)
: devolve os nomes das propriedades den
.TO_JSON(n)
: devolven
no formato JSON. Para mais informações, consulte a funçãoTO_JSON
.
O predicado PROPERTY_EXISTS
,a função LABELS
e a função TO_JSON
, bem como outras funções integradas, como ARRAY_AGG
e CONCAT
.
GRAPH FinGraph
MATCH (person:Person)-[:Owns]->(account:Account)
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person
NEXT
RETURN
LABELS(person) AS labels,
TO_JSON(person) AS person,
accounts,
CONCAT(person.city, ", ", person.country) AS location,
PROPERTY_EXISTS(person, is_blocked) AS is_blocked_property_exists,
PROPERTY_EXISTS(person, name) AS name_property_exists
LIMIT 1;
Resultado
is_blocked_property_exists | name_property_exists | etiquetas | contas | localização | pessoa |
---|---|---|---|---|---|
falso | verdadeiro | Pessoa | ["Vacation Fund"] | Adelaide, Austrália | {"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}} |
Subconsultas
Uma subconsulta é uma consulta aninhada noutra consulta. As seguintes listas regras de subconsulta do gráfico do Spanner:
- Uma subconsulta está entre um par de chavetas
{}
. - Uma subconsulta pode começar com a cláusula
GRAPH
inicial para especificar o gráfico no âmbito. O gráfico especificado não tem de ser o mesmo que o usado na consulta externa. - Quando a cláusula
GRAPH
é omitida na subconsulta, ocorre o seguinte:- O gráfico no âmbito é inferido a partir do contexto de consulta externo mais próximo.
- A subconsulta tem de começar por uma declaração de correspondência de padrão de grafos
com o
MATCH.
- Não é possível declarar novamente uma variável de padrão de gráfico declarada fora do âmbito da subconsulta, mas pode ser referida em expressões ou funções dentro da subconsulta.
Use uma subconsulta para encontrar o número total de transferências de cada conta
A consulta seguinte ilustra a utilização da subconsulta VALUE
. A subconsulta está
entre chavetas {}
precedidas pela palavra-chave VALUE
. A consulta devolve o número total de transferências iniciadas a partir de uma conta.
GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
MATCH (a:Account)-[transfer:Transfers]->(:Account)
WHERE a = account
RETURN COUNT(transfer) AS num_transfers
} AS num_transfers;
Resultado
nome | account_id | num_transfers |
---|---|---|
Alex | 7 | 2 |
Dana | 20 | 2 |
Lee | 16 | 1 |
Para ver uma lista das expressões de subconsulta suportadas, consulte o artigo Subconsultas do Spanner Graph.
Parâmetros de consulta
Pode consultar o Spanner Graph com parâmetros. Para mais informações, consulte a sintaxe e saiba como consultar dados com parâmetros nas bibliotecas de cliente do Spanner.
A consulta seguinte ilustra a utilização de parâmetros de consulta.
GRAPH FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;
Consultar gráficos e tabelas em conjunto
Pode usar consultas de gráficos em conjunto com SQL para aceder a informações dos seus gráficos e tabelas numa única declaração.
GRAPH_TABLE
O operador GRAPH_TABLE
recebe uma consulta de gráfico linear e devolve o respetivo resultado num formato tabular que pode ser integrado perfeitamente numa consulta SQL. Esta interoperabilidade permite-lhe enriquecer os resultados das consultas de grafos com conteúdo não gráfico e vice-versa.
Por exemplo, pode criar uma tabela CreditReports
e inserir alguns relatórios de crédito, como mostrado no exemplo seguinte:
CREATE TABLE CreditReports (
person_id INT64 NOT NULL,
create_time TIMESTAMP NOT NULL,
score INT64 NOT NULL,
) PRIMARY KEY (person_id, create_time);
INSERT INTO CreditReports (person_id, create_time, score)
VALUES
(1,"2020-01-10 06:22:20.222", 700),
(2,"2020-02-10 06:22:20.222", 800),
(3,"2020-03-10 06:22:20.222", 750);
Em seguida, identifique pessoas de interesse através da correspondência de padrões de grafos no
GRAPH_TABLE
e junte os resultados da consulta de grafos à tabela CreditReports
para
aceder a uma classificação de crédito.
SELECT
gt.person.id,
credit.score AS latest_credit_score
FROM GRAPH_TABLE(
FinGraph
MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account {is_blocked:true})
RETURN DISTINCT person
) AS gt
JOIN CreditReports AS credit
ON gt.person.id = credit.person_id
ORDER BY credit.create_time;
Resultado:
person_id | latest_credit_score |
---|---|
1 | 700 |
2 | 800 |
O que se segue?
Saiba mais sobre as práticas recomendadas para otimizar consultas.