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 spannerEnvie um comando através do comando
gcloud spanner databases execute-sql.A API REST
executeSqleexecuteStreamingSqlA API RPC
ExecuteSqleExecuteStreamingSql
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
Accounttêm a propriedadecreate_time, mas não têm a propriedadebirthday. É devolvido umNULLpara a propriedadebirthdaypara esses nós. - Os nós correspondentes à etiqueta
Persontêm a propriedadebirthday, mas não têm a propriedadecreate_time. É devolvido umNULLpara a propriedadecreate_timepara 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
WHEREe.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 senexpõ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): devolvenno 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
GRAPHinicial 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.