Optimaliser GQL-spørringsytelsen for graf i Microsoft Fabric

Denne artikkelen gir veiledning for å skrive GQL (Graph Query Language)-spørringer som fungerer forutsigbart og effektivt når man arbeider med graf i Microsoft Fabric. Anbefalingene er basert på dagens plattformadferd og dokumenterte begrensninger.

For harde grenser for grafstørrelse, resultatstørrelse og spørringstidsavbrudd, se Nåværende begrensninger. Flere anbefalinger i denne artikkelen gjelder også hvordan du designer grafskjemaet ditt. For mer informasjon, se Design et grafskjema.

Plasser filtre i henhold til deres semantikk

Plasser et predikat inne i et grafmønster når det definerer hvilken node eller kant som kan delta i matchen. Bruk en setningsnivåbetingelse MATCH ... WHERE for å etterfiltrere den fullførte matchen, eller en separat FILTER setning når predikatet gjelder for raden produsert av en tidligere setning.

For eksempel, bruk mønsternivå-klausuler WHERE for betingelser på de matchede nodene:

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

En separat FILTER kan uttrykke samme betingelse etter en vanlig obligatorisk match som bruker standard ALL stisøk:

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

Spørringsoptimalisatoren kan bruke ekvivalente predikater under skanning, men dette bevarer spørringssemantikken, så inline-syntaksen er ikke nødvendigvis raskere. Velg skjemaet som uttrykker når betingelsen gjelder.

Predikatplassering kan endre resultater med ANY SHORTEST. Inline-predikater begrenser stiene som er kvalifisert for valg av korteste sti. Et statement-nivå WHERE eller påfølgende FILTER gjelder etter valg av sti, slik at det kan fjerne en valgt korteste sti uten å velge en lengre sti i stedet. For den nåværende MATCH ... WHERE begrensningen og et pålitelig plasseringsmønster, se Plasser-predikater før eller etter stivalg.

Plassering har også betydning med OPTIONAL MATCH, hvor en inline WHERE begrenser den valgfrie matchen, men en påfølgende FILTER kan fjerne null-utvidet rad.

Tips

Tenk på mønsternivå WHERE som analogt med en SQL-betingelse JOIN ... ON . Den beskriver hvilke matcher som kvalifiserer, i stedet for å filtrere den resulterende raden etterpå.

Returner kun de eiendommene du trenger

Returner kun node- og kantegenskapene som scenarioet ditt krever. Unngå å returnere hele noder eller bruke RETURN * når du bare trenger et delsett av egenskaper.

Å velge unødvendige egenskaper øker datalesing, serialiseringskostnader og responsstørrelse. Under grafmodellering, velg kun kildekolonnene du trenger som nodetype-egenskaper.

Anbefalt: Smal projeksjon.

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

Unngå: Returnerer fulle noder.

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

Bemerkning

Legg kun til nodetype-egenskaper under grafmodellering når de trengs for spørringer eller analyse. Færre egenskaper per node reduserer både storage- og query-overhead.

Begrenset resultatmengdestørrelse

Bruk LIMIT eller andre avgrensningsbetingelser når du spør noder eller relasjoner som kan ha høy kardinalitet. Ubegrensede grafmatcher kan produsere svært store resultatsett som nærmer seg plattformgrenser.

Anbefalt: Begrensede resultater.

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

Unngå: Ubegrenset høy-kardinalitets-match.

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

Viktig!

Grafen avkorter spørringssvar hvis interne binærrepresentasjon overstiger 64 MB. Et avkortet svar inkluderer en tilleggsstatus med offentlig kode 01000 og kanonisk GQL-status 01M11. Bruk filtre, smale projeksjoner og LIMIT for å redusere resultatstørrelsen. For mer informasjon, se Nåværende begrensninger.

Hold traverseringene grunne og målrettede

Unngå dypt nestede eller svært komplekse grafmønstre. Bruk enkle, målrettede traverser som direkte svarer på et spesifikt spørsmål. Hvert ekstra hopp i et mønster med variabel lengde kan eksponentielt øke antallet baner motoren evaluerer, spesielt i tett sammenhengende grafer.

Anbefalt: Stramme grenser.

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

Unngå: Et bredt bevegelsesområde uten åpenbart behov.

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

Viktig!

Den visuelle spørringsbyggeren begrenser baner med variabel lengde til åtte hopp, men denne brukergrensesnittgrensen gjelder ikke for GQL i kodeeditoren. Bruk den strammeste grensen scenarioet ditt tillater, fordi et bredere område kan matche flere veier.

Bruk TRAIL når stier ikke må gjenta kanter

Bruk TRAIL stimodus når en gyldig sti ikke må gjenta en kant. I grafer med sykluser kan denne begrensningen også redusere antall matchende stier sammenlignet med standardmodusen 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

Uten TRAIL, kan samme spørring på en syklisk graf returnere stier som gjentar en kant. Bruk modusen som matcher den nødvendige sti-semantikken i stedet for å behandle TRAIL det som en generell ytelsesoptimalisering.

Et ubegrenset ALL WALK mønster støttes ikke fordi sykluser kan produsere uendelig mange stier. Selv om ubundne TRAIL, SIMPLE, og ACYCLIC mønstre avsluttes, kan de fortsatt liste opp mange stier. Bruk en endelig øvre grense med mindre spørringen krever ubegrenset traversering.

Bruk delte variabler for effektive joins

Når en spørring krever data fra flere relasjoner, bruk en delt variabel for å koble til mønstre på samme enhet. Uten en delt variabel kan mønstre produsere et kartesisk produkt – hver kombinasjon av treff fra begge mønstrene – noe som fører til et mye større resultatsett.

Anbefalt: Delt variabel p kobler seg til mønstrene.

-- 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

Unngå: Uavhengige mønstre uten delt variabel.

-- 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

Et kartesisk produkt parer hvert resultat fra ett mønster med hvert resultat fra det andre. Hvis Person-workAt->Company matcher 1 000 rader og Person-isLocatedIn->City matcher 500 rader, returnerer spørringen 1 000 × 500 = 500 000 rader. Å legge til en delt variabel begrenser joinen slik at kun matchende par returneres.

Filtrer på nøkkelegenskaper når du identifiserer noder

Definer nodenøkkelbegrensninger for å identifisere noder unikt og håndheve dataintegritet. Når du trenger én spesifikk node, inkluder dens nøkkelegenskap i mønsterpredikatet for å unngå å matche ikke-relaterte noder.

For eksempel, hvis graftypen din definerer id som nøkkelen for Person noder:

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

Deretter filtrerer du på id når du trenger den personen:

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

Uten filteret matcher spørringen hver Person node før den passerer workAt kantene:

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

Tips

En nøkkelbegrensning etablerer identitet og unikhet. Det garanterer ikke i seg selv et bestemt fysisk søk eller forespørselsplan.

Velg aktuelle datatyper

Velg datatypen som representerer hver eiendoms verdier og tiltenkte operasjoner. For eksempel, bruk en numerisk type for verdier du beregner eller sammenligner numerisk, i stedet for å lagre formaterte tall som strenger.

For støttede datatyper, se Nåværende begrensninger — Datatyper og Støttede egenskapstyper.

Der det er mulig, hent relaterte enheter i et enkelt grafmønster i stedet for å sende separate spørringer som går uavhengig gjennom de samme kantene. Å kombinere traverseringer unngår overflødig mønstergjenkjenning og forhindrer N+1-spørringsproblemet, hvor én innledende spørring utløser en separat spørring for hver resultatrad.

Anbefalt: Enkelt kombinert mønster.

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

Unngå: To separate forespørsler som går langs samme Customer → Order kant.

-- 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

Testforespørsler mot realistiske datavolumer

Spørringer som presterer godt på små datasett, skalerer kanskje ikke lineært. Test spørringene dine med datavolumer som representerer forventet produksjonsarbeidsmengde.

  • Foretrekk konservative spørringsformer som inkluderer filtre og grenser.
  • Unngå utforskende «returner alt»-spørringer mot store grafer.
  • Overvåk spørringstiden i forhold til 20-minutters tidsavslutningsgrensen.