Otimizar o desempenho das consultas GQL para grafos no Microsoft Fabric

Este artigo fornece orientações para escrever consultas GQL (Graph Query Language) que funcionam de forma previsível e eficiente ao trabalhar com grafos no Microsoft Fabric. As recomendações baseiam-se no comportamento atual da plataforma e nas restrições documentadas.

Para limites rígidos de tamanho do grafo, tamanho do resultado e tempo de espera da consulta, veja Limitações atuais. Algumas recomendações neste artigo também se relacionam com a forma como desenha o seu esquema de grafos. Para mais informações, consulte Desenhar um esquema de grafo.

Coloque filtros de acordo com a sua semântica

Coloque um predicado dentro de um padrão de grafo quando este define qual nó ou aresta pode participar na correspondência. Use uma condição MATCH ... WHERE ao nível da instrução para filtrar posteriormente a correspondência concluída, ou uma instrução FILTER separada quando o predicado se aplicar à linha produzida por uma instrução anterior.

Por exemplo, use cláusulas WHERE ao nível do padrão para definir condições sobre os nós correspondentes:

MATCH (p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.id > 1000)
RETURN p.firstName, p.lastName, c.name

Um FILTER separado pode expressar a mesma condição após uma correspondência obrigatória normal que utiliza a procura de caminho predefinida ALL:

MATCH (p:Person)-[:workAt]->(c:Company)
FILTER p.birthday < 19940101 AND c.id > 1000
RETURN p.firstName, p.lastName, c.name

O otimizador de consultas pode aplicar predicados equivalentes durante a varredura, quando isso preserva a semântica da consulta, pelo que a sintaxe inline não é inerentemente mais rápida. Escolha a forma que expressa quando a condição se aplica.

A colocação de predicados pode alterar os resultados com ANY SHORTEST. Os predicados em linha restringem os caminhos elegíveis para seleção do caminho mais curto. Um WHERE ao nível da instrução ou um FILTER subsequente aplica-se após a seleção de caminho, pelo que pode remover o caminho mais curto selecionado sem, em vez disso, escolher um caminho mais longo. Para a limitação atual MATCH ... WHERE e um padrão de colocação fiável, veja Colocar predicados antes ou depois da seleção do caminho.

A posição também importa com OPTIONAL MATCH, onde um WHERE em linha restringe a correspondência opcional, mas um FILTER subsequente pode remover a linha expandida com valores nulos.

Sugestão

Pensa no nível WHERE de padrão como análogo a uma condição SQL JOIN ... ON . Descreve que correspondências satisfazem os critérios, em vez de filtrar posteriormente a linha resultante.

Devolva apenas as propriedades de que precisa

Retorne apenas as propriedades do nó e da aresta que o seu cenário exige. Evite devolver nós completos ou usar RETURN * quando precisa apenas de um subconjunto de propriedades.

Selecionar propriedades desnecessárias aumenta a leitura dos dados, o custo de serialização e o tamanho da resposta. Durante a modelação de grafos, selecione apenas as colunas de origem de que necessita como propriedades do tipo de nó.

Recomendado: Projeção estreita.

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name

Evitar: Retornar nodos completos.

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN *

Observação

Só adicione propriedades de tipo de nó durante a modelação de grafos quando forem necessárias para consultas ou análises. Menos propriedades por nó reduzem tanto a sobrecarga de armazenamento quanto a de consulta.

Limitar tamanho do conjunto de resultados

Aplicar LIMIT ou outras condições de limite ao consultar nós ou relações que possam ter alta cardinalidade. Correspondências ilimitadas de grafos podem gerar conjuntos de resultados muito grandes que se aproximam dos limites da plataforma.

Recomendado: Resultados limitados.

MATCH (p:Person)-[:knows]->(friend:Person)
RETURN p.firstName, friend.firstName
LIMIT 1000

Evitar: Jogo ilimitado de alta cardinalidade.

MATCH (p:Person)-[:knows]->(friend:Person)
RETURN p.firstName, friend.firstName

Importante

O grafo trunca respostas de consulta cuja representação binária interna excede 64 MB. Uma resposta truncada inclui um estado adicional com o código público 01000 e o GQLSTATUS canónico 01M11. Utilize filtros, projeções limitadas e LIMIT para reduzir o tamanho do resultado. Para obter mais informações, consulte Limitações atuais.

Mantenha os percursos rasos e direcionados

Evite padrões de grafos profundamente aninhados ou altamente complexos. Utilize percursos simples e direcionados que respondam praticamente a uma pergunta específica. Cada salto extra num padrão de comprimento variável pode aumentar exponencialmente o número de caminhos que o motor avalia, especialmente em grafos densamente conexos.

Recomendado: Limites apertados.

-- Use the narrowest hop range that answers your question
MATCH (p:Person)-[:knows]->{1,3}(friend:Person)
RETURN p.firstName, friend.firstName
LIMIT 1000

Evitar: Uma ampla amplitude de deslocamento sem uma necessidade clara.

-- A wider range on a dense graph is more expensive
MATCH (p:Person)-[:knows]->{1,8}(friend:Person)
RETURN *

Importante

O construtor visual de consultas limita caminhos de comprimento variável a oito saltos, mas este limite da interface de utilizador não se aplica ao GQL no editor de código. Usa o limite mais apertado que o teu cenário permitir, porque um alcance mais amplo pode corresponder a mais caminhos.

Utilize TRAIL quando os caminhos não devem repetir arestas

Use o modo de caminho TRAIL quando um caminho válido não pode repetir uma aresta. Em grafos com ciclos, esta restrição também pode reduzir o número de caminhos correspondentes em comparação com o modo padrão WALK .

-- TRAIL prevents revisiting the same :knows edge
MATCH TRAIL (src:Person)-[:knows]->{1,4}(dst:Person)
WHERE src.firstName = 'Alice' AND dst.firstName = 'Bob'
RETURN count(*) AS numPaths

Sem TRAIL, a mesma consulta num grafo cíclico pode devolver caminhos que repetem uma aresta. Use o modo que corresponda à semântica de caminho necessária em vez de o tratar TRAIL como uma otimização geral de desempenho.

Um padrão ilimitado ALL WALK não é suportado porque os ciclos podem produzir infinitos caminhos. Embora ilimitados TRAIL, SIMPLE, e ACYCLIC padrões terminem, ainda podem enumerar muitos caminhos. Use um limite superior finito, a menos que a consulta exija uma travessia ilimitada.

Use variáveis partilhadas para junções eficientes

Quando uma consulta requer dados de múltiplas relações, use uma variável partilhada para ligar padrões na mesma entidade. Sem uma variável partilhada, os padrões podem produzir um produto cartesiano – cada combinação de correspondências de ambos os padrões – levando a um conjunto de resultados muito maior.

Recomendado: A variável p partilhada junta-se aos padrões.

-- Single shared variable ensures an efficient join
MATCH (p:Person)-[:workAt]->(c:Company),
      (p)-[:isLocatedIn]->(city:City)
RETURN p.firstName, c.name AS company, city.name AS city
LIMIT 1000

Evitar: Padrões independentes sem variável partilhada.

-- Without a shared variable, this produces a cartesian product
MATCH (p1:Person)-[:workAt]->(c:Company),
      (p2:Person)-[:isLocatedIn]->(city:City)
RETURN p1.firstName, c.name, p2.firstName, city.name

Um produto cartesiano emparelha cada resultado de um padrão com cada resultado do outro. Se Person-workAt->Company corresponder a 1.000 linhas e Person-isLocatedIn->City corresponder a 500 linhas, a consulta devolve 1.000 × 500 = 500.000 linhas. Adicionar uma variável partilhada restringe a junção, de modo que apenas os pares correspondentes são devolvidos.

Filtrar por propriedades principais ao identificar nós

Defina as restrições das chaves dos nós para identificar os nós de forma única e garantir a integridade dos dados. Quando precisar de um nó específico, inclua a sua propriedade-chave no predicado do padrão para evitar a correspondência com nós não relacionados.

Por exemplo, se o seu tipo de grafo define id como chave para os nós Person:

CONSTRAINT person_pk
  FOR (n:Person) REQUIRE n.id IS KEY

Depois filtra por id quando precisares dessa pessoa:

MATCH (p:Person WHERE p.id = 12345)-[:workAt]->(c:Company)
RETURN p.firstName, c.name

Sem o filtro, a consulta corresponde a todos Person os nós antes de atravessar workAt as arestas:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, c.name

Sugestão

Uma restrição chave estabelece identidade e unicidade. Por si só, não garante uma procura física específica nem um plano de consulta específico.

Escolha os tipos de dados apropriados

Selecione o tipo de dado que represente os valores e operações pretendidas de cada propriedade. Por exemplo, use um tipo numérico para valores que calcule ou compare numericamente em vez de armazenar números formatados como cadeias de caracteres.

Para tipos de dados suportados, veja Limitações atuais — Tipos de dados e Tipos de propriedade suportados.

Sempre que possível, recuperar entidades relacionadas num único padrão de grafo em vez de emitir consultas separadas que percorram as mesmas arestas de forma independente. Combinar percursos evita a correspondência redundante de padrões e previne o problema de N+1 consultas, onde uma consulta inicial desencadeia uma consulta separada para cada linha de resultados.

Recomendado: Padrão combinado único.

MATCH (c:Customer)-[:purchases]->(o:`Order`)-[:`contains`]->(product:`Product`)
RETURN c.fullName, o, product.productName
LIMIT 1000

Evitar: Duas consultas separadas que atravessam a mesma Customer → Order aresta.

-- Query 1: fetch 100 orders
MATCH (c:Customer)-[:purchases]->(o:`Order`)
RETURN c.fullName, o
LIMIT 100

-- Query 2: repeat for each returned order, substituting its key value
MATCH (o:`Order` WHERE o.SalesOrderDetailID_K = 12345)-[:`contains`]->(product:`Product`)
RETURN o, product.productName

Testar consultas com volumes de dados realistas

Consultas que têm bom desempenho em conjuntos de dados pequenos podem não escalar linearmente. Teste as suas consultas com volumes de dados que representem a sua carga de trabalho de produção esperada.

  • Prefiro formas de consulta conservadoras que incluam filtros e limites.
  • Evite consultas "devolver tudo" exploratórias em grafos grandes.
  • Monitorize a duração da consulta em relação ao limite de tempo limite de 20 minutos.