共用方式為


優化 Microsoft Fabric 圖形的 GQL 查詢效能

備註

這項功能目前處於公開預覽狀態。 此預覽版是在沒有服務等級協定的情況下提供,不建議用於生產工作負載。 可能不支援特定功能,或可能已經限制功能。 欲了解更多資訊,請參閱Microsoft Azure預覽補充使用條款

本文提供撰寫 GQL(圖查詢語言)查詢的指導,以確保在 Microsoft Fabric 中操作圖時,查詢能夠穩定且高效地執行。 這些建議是根據目前平台的行為和文件上的限制條件提出的。

關於圖大小、結果大小及查詢逾時的硬性限制,請參見 「目前限制」。

在模式中早期進行過濾

將濾波器置於圖形模式中,而非後續陳述中。 模式層 WHERE 級子句減少了連接前及後續語句執行前的中間結果數量,從而降低整體執行成本。

推薦: 在模式匹配時進行篩選。

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

避免: 延遲過濾,並使用獨立的 FILTER 語句。

-- Statement-level filter runs after all pattern matches are produced
MATCH (p:Person)-[:workAt]->(c:Company)
FILTER p.birthday < 19940101 AND c.id > 1000
RETURN p.firstName, p.lastName, c.name

兩個查詢回傳相同的結果,但第一個版本允許查詢引擎在評估過程中較早修剪資料列。

小提示

可將模式層 WHERE 視為 SQL JOIN ... ON 條件。 它在評估時限制匹配,而非對完整結果集進行後期過濾。

只回傳你需要的屬性

只回傳你情境所需的節點和邊緣屬性。 避免回傳完整節點或在只需部分屬性的情況下使用RETURN *

在圖中,OneLake 會回溯節點屬性。 選擇不必要的屬性會增加資料讀取、序列化成本及響應大小。 在圖建模過程中,除非移除,否則所有來自來源資料表的欄位預設都會被加入為屬性。

建議: 窄投射。

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

避免: 回傳全結點。

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

備註

在圖建模過程中,請選擇每個屬性旁的垃圾桶圖示來移除未使用的屬性。 每個節點的屬性數量減少時,能同時降低儲存和查詢的負擔。

結果集大小限制

查詢可能基數高的節點或關係時,應用 LIMIT 或其他限制條件。 無界圖匹配能產生非常龐大的結果集,接近平台極限。

推薦: 結果有界。

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

避免: 無界高基數匹配。

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

這很重要

圖表會截斷超過 64 MB 的回應,當結果超過 128 MB 時,聚合效能可能不穩定。 使用 FILTERLIMITGROUP BY 以保持結果在這些範圍內。 如需詳細資訊,請參閱目前的限制

保持遍歷淺且具針對性

避免深度巢式或高度複雜的圖型態。 偏好簡單且有針對性的穿越,直接回答特定問題。 在可變長度模式中,每多跳一次,引擎評估的路徑數量都會呈指數增加,尤其是在密集連結的圖中。

推薦: 緊密的限制。

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

避免: 在沒有明確需求的情況下進行最大深度遍歷。

-- Exploring the full 8-hop limit on a dense graph is expensive
MATCH (p:Person)-[:knows]->{1,8}(friend:Person)
RETURN *

這很重要

圖形支援最多 八次跳躍 的可變長度模式。 即便如此,還是要用你情境允許的最嚴格範圍。 在這個例子中,{1,3} 模式在同一圖表上比 {1,8} 便宜許多。

使用 TRAIL 來防止重複的穿越

使用 TRAIL 路徑模式來防止查詢引擎重複探索同一邊。 在密集圖中,循環可能導致指數路徑爆炸。 TRAIL 確保在每條路徑上最多只能造訪每條邊一次,這不僅提升了正確性,也提升了效能。

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

若沒有 TRAIL,循環圖上的相同查詢可以產生更大(且常常冗餘)的結果集。

使用共享變數來促進有效率的連接

當查詢需要來自多個關係的資料時,使用共享變數將模式連結在同一實體上。 若沒有共享變數,模式可能會產生笛卡兒積——即兩種模式的匹配組合——進而產生更大的結果集。

推薦閱讀: 共享變數 p 會加入這些模式。

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

避免: 獨立的模式,沒有共享變數。

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

笛卡兒積會將一個圖案的每個結果與另一個圖案的結果配對。 若 Person-workAt->Company 匹配 1,000 列且 Person-isLocatedIn->City 匹配 500 列,查詢回傳 1,000 × 500 = 500,000 列。 加入共享變數會限制連接,因此只會回傳匹配的變數對。

定義節點上的關鍵約束

在你的圖類型中定義 節點鍵限制 。 金鑰限制使系統能優化查詢,透過特定節點的金鑰屬性查詢,類似關聯式資料庫中的主鍵索引。

例如,如果你的圖型別定義 id 作為節點的鍵 Person

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

然後,經過篩選的 id 查詢就可以直接使用該鍵來查找:

-- Fast: the engine can look up person 12345 directly using the key
MATCH (p:Person WHERE p.id = 12345)-[:workAt]->(c:Company)
RETURN p.firstName, c.name

若沒有對金鑰屬性的濾波器,引擎必須掃描每個 Person 節點:

-- Slower: scans all Person nodes before traversing
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, c.name

小提示

當你需要特定節點時,可以在模式中對其金鑰屬性 MATCH 進行過濾,以利用你定義的限制條件。

選擇適當的數據類型

在圖建模時,為每個物業選擇最具體的資料類型。 選擇合適的類型對 storage 效率和查詢效能都很重要。 例如,對 INT 性質進行數值比較比對等價 STRING 值的字串比較更快。

關於支援的資料型態,請參見 「目前限制 — 資料型別 」及 「支援屬性型別」。

若可能,請以單一圖模式檢索相關實體,而非分別發出獨立遍歷相同邊的查詢。 結合遍歷可避免冗餘的模式匹配,並避免 N+1 查詢問題,即一次初始查詢觸發每個結果列的獨立查詢。

推薦:單一組合圖案。

MATCH (c:Customer)-[:purchased]->(o:Order)-[:contains]->(product:Product)
RETURN c.id, o.id, product.name
LIMIT 1000

避免: 兩個獨立的查詢,穿越相同的 Customer → Order 邊。

-- Query 1: fetch 100 orders
MATCH (c:Customer)-[:purchased]->(o:Order)
RETURN c.id, o.id

-- Query 2: run once per order to get products (N+1 problem)
MATCH (o:Order)-[:contains]->(product:Product)
RETURN o.id, product.name

針對現實資料量進行測試查詢

在小型資料集上表現良好的查詢,可能無法線性擴展。 用代表預期生產工作負載的資料量來測試你的查詢。

  • 偏好包含篩選條件與限制的保守查詢格式。
  • 避免對大型圖表進行探索性的「回傳全部」查詢。
  • 監控查詢的持續時間與 20 分鐘超時限制的關係。