Optymalizowanie wydajności zapytań GQL dla grafu w Microsoft Fabric

Ten artykuł zawiera wskazówki dotyczące pisania zapytań GQL (Graph Query Language), które wykonują przewidywalnie i wydajnie podczas pracy z grafem w Microsoft Fabric. Zalecenia są oparte na bieżącym zachowaniu platformy i udokumentowanych ograniczeniach.

Aby uzyskać twarde limity dotyczące rozmiaru grafu, rozmiaru wyników i limitu czasu zapytania, zobacz Bieżące ograniczenia. Kilka zaleceń w tym artykule dotyczy również sposobu projektowania schematu grafu. Aby uzyskać więcej informacji, zobacz Projektowanie schematu grafu.

Umieść filtry zgodnie z ich semantyką

Umieść predykat wewnątrz wzorca grafu, gdy definiuje, który węzeł lub krawędź może uczestniczyć w dopasowaniu. Użyj warunku MATCH ... WHERE na poziomie instrukcji, aby odfiltrować ukończone dopasowanie, lub osobnej instrukcji FILTER, gdy predykat dotyczy wiersza utworzonego przez wcześniejszą instrukcję.

Na przykład użyj klauzul WHERE na poziomie wzorca do określania warunków dla dopasowanych węzłów:

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

Oddzielne FILTER może wyrazić ten sam warunek po zwykłym obowiązkowym dopasowaniu wykorzystującym domyślne ALL wyszukiwanie ścieżek:

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

Optymalizator zapytań może stosować równoważne predykaty podczas skanowania, co zachowuje semantykę zapytań, więc składnia inline nie jest z natury szybsza. Wybierz formularz, który wyraża, kiedy warunek ma zastosowanie.

Umiejscowienie predykatu może zmienić wyniki w przypadku ANY SHORTEST. Predykaty inline ograniczają ścieżki kwalifikujące się do wyboru najkrótszej ścieżki. WHERE na poziomie instrukcji lub kolejne FILTER ma zastosowanie po wybraniu ścieżki, a tym samym może usunąć wybraną najkrótszą ścieżkę bez wybrania w zamian dłuższej. Informacje o obecnych ograniczeniach MATCH ... WHERE oraz niezawodnym sposobie rozmieszczania znajdziesz w artykule Umieszczaj predykaty przed wyborem ścieżki lub po nim.

Rozmieszczenie ma również znaczenie przy OPTIONAL MATCH, gdzie inline WHERE ogranicza opcjonalne dopasowanie, ale kolejne FILTER może usunąć zerowy rozszerzony wiersz.

Wskazówka

Należy traktować poziom WHERE wzorca jako analogiczny do warunku SQL JOIN ... ON . Opisuje, które dopasowania spełniają kryteria, zamiast później filtrować wynikowy wiersz.

Zwracanie tylko potrzebnych właściwości

Zwróć tylko właściwości węzła i krawędzi wymagane przez twój scenariusz. Unikaj zwracania pełnych węzłów lub używania RETURN * , jeśli potrzebujesz tylko podzestawu właściwości.

Wybranie niepotrzebnych właściwości zwiększa odczyt danych, koszt serializacji i rozmiar odpowiedzi. Podczas modelowania grafu wybierz tylko kolumny źródłowe, które są potrzebne jako właściwości typu węzła.

Zalecane: Wąska projekcja.

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

Unikaj: Zwracanie pełnych węzłów.

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

Uwaga / Notatka

Dodaj właściwości typu węzła podczas modelowania grafu tylko wtedy, gdy są one potrzebne do wykonywania zapytań lub analiz. Mniejsza liczba właściwości na węzeł zmniejsza zarówno obciążenie magazynowania, jak i zapytań.

Ogranicz rozmiar zestawu wyników

Zastosuj LIMIT lub inne warunki ograniczenia podczas wykonywania zapytań dotyczących węzłów lub relacji, które mogą mieć wysoką kardynalność. Nieograniczone dopasowania grafu mogą generować bardzo duże zestawy wyników, które zbliżają się do limitów platformy.

Zalecane: Ograniczone wyniki.

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

Unikać: Dopasowanie o wysokiej kardynalności bez ograniczeń.

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

Ważna

Graph skraca odpowiedzi zapytań, których wewnętrzna reprezentacja binarna przekracza 64 MB. Skrócona odpowiedź zawiera dodatkowy status zawierający publiczny kod 01000 i kanoniczny GQLSTATUS 01M11. Używaj filtrów, wąskich projekcji i LIMIT, aby zmniejszyć rozmiar wyniku. Aby uzyskać więcej informacji, zobacz Bieżące ograniczenia.

Zachowaj płytkość i ukierunkowanie podczas przechodzenia

Unikaj głęboko zagnieżdżonych lub wysoce złożonych wzorców grafów. Używaj prostych, ukierunkowanych przejść, które bezpośrednio odpowiadają na konkretne zagadnienie. Każdy dodatkowy przeskok we wzorcu o zmiennej długości może wykładniczo zwiększyć liczbę ścieżek ocenianych przez silnik, zwłaszcza w gęsto połączonych grafach.

Zalecane: Ciasne granice.

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

Unikaj: Szerokiego zakresu przemieszczania się bez wyraźnej potrzeby.

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

Ważna

Wizualny kreator zapytań ogranicza ścieżki o zmiennej długości do ośmiu skoków, ale to ograniczenie interfejsu użytkownika nie dotyczy GQL w edytorze kodu. Użyj najwęższego ograniczenia, na jakie pozwala dany scenariusz, ponieważ szerszy zakres może pasować do większej liczby ścieżek.

Używaj TRAIL, gdy ścieżki nie mogą powtarzać krawędzi

Używaj TRAIL trybu ścieżki, gdy prawidłowa ścieżka nie może powtarzać krawędzi. W grafach z cyklami to ograniczenie może również zmniejszyć liczbę ścieżek dopasowania w porównaniu do trybu domyślnego 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

Bez TRAIL, to samo zapytanie na graf cykliczny może zwracać ścieżki powtarzające krawędź. Używaj trybu odpowiadającego wymaganej semantyce ścieżek, zamiast traktować TRAIL jako ogólną optymalizację wydajności.

Wzorzec nieograniczony ALL WALK nie jest wspierany, ponieważ cykle mogą generować nieskończenie wiele ścieżek. Chociaż wzorce TRAIL, SIMPLE i ACYCLIC są nieograniczone, to jednak się kończą, ale nadal mogą generować wiele ścieżek. Używaj skończonej górnej granicy, chyba że zapytanie wymaga nieograniczonego przeszukiwania.

Używanie zmiennych udostępnionych do wydajnych sprzężeń

Jeśli zapytanie wymaga danych z wielu relacji, użyj zmiennej udostępnionej, aby połączyć wzorce w tej samej jednostce. Bez udostępnionej zmiennej wzorce mogą tworzyć produkt kartezjański - każda kombinacja dopasowań z obu wzorców - co prowadzi do znacznie większego zestawu wyników.

Zalecane: Współdzielona zmienna p łączy wzorce.

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

Unikaj: Niezależne wzorce bez współdzielonej zmiennej.

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

Kartezjański produkt paruje każdy wynik z jednego wzorca z każdym wynikiem z drugiego. Jeśli Person-workAt->Company pasuje do 1000 wierszy i Person-isLocatedIn->City pasuje do 500 wierszy, zapytanie zwraca 1000 × 500 = 500 000 wierszy. Dodanie zmiennej udostępnionej ogranicza operację łączenia, aby zwracane były tylko pasujące pary.

Filtrowanie kluczowych właściwości podczas identyfikacji węzłów

Zdefiniuj ograniczenia klucza węzłów , aby jednoznacznie je identyfikować i wymuszać integralność danych. Gdy potrzebujesz jednego konkretnego węzła, uwzględnij jego właściwość klucza w predykacie wzorca, aby uniknąć dopasowania niepowiązanych węzłów.

Na przykład, jeśli typ grafu definiuje id jako klucz węzłów Person:

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

Następnie filtruj według id, gdy potrzebujesz tej osoby:

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

Bez filtra zapytanie dopasowuje każdy węzeł Person przed przejściem przez krawędzie workAt:

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

Wskazówka

Ograniczenie klucza określa tożsamość i unikalność. To samo w sobie nie gwarantuje konkretnego fizycznego planu wyszukiwania czy zapytania.

Wybieranie odpowiednich typów danych

Wybierz typ danych, który reprezentuje wartości i zamierzone operacje każdej właściwości. Na przykład użyj typu numerycznego dla wartości, które obliczasz lub porównujesz numerycznie, zamiast przechowywać sformatowane liczby jako ciągi znaków.

Aby uzyskać informacje o obsługiwanych typach danych, zobacz Bieżące ograniczenia — typy danych i obsługiwane typy właściwości.

Jeśli to możliwe, pobierz powiązane jednostki w jednym wzorcu grafu zamiast wystawiać oddzielne zapytania, które przechodzą przez te same krawędzie niezależnie. Połączenie przechodzenia pozwala uniknąć nadmiarowego dopasowywania wzorca i zapobiega problemowi z zapytaniem N+1, w którym jedno zapytanie początkowe wyzwala oddzielne zapytanie dla każdego wiersza wyników.

Zalecane: Pojedynczy zintegrowany wzorzec.

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

Unikaj: Dwa oddzielne zapytania przechodzące przez tę samą Customer → Order krawędź.

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

Testowanie zapytań względem realistycznych woluminów danych

Zapytania, które działają dobrze na małych zestawach danych, mogą nie być skalowane liniowo. Przetestuj zapytania przy użyciu woluminów danych reprezentujących oczekiwane obciążenie produkcyjne.

  • Preferuj konserwatywne kształty zapytań, które obejmują filtry i limity.
  • Unikaj eksploracyjnych zapytań "zwracaj wszystko" względem dużych grafów.
  • Monitoruj czas trwania zapytania względem limitu czasu 20 minut.