通过


优化 Microsoft Fabric 中图形的 GQL 查询性能

注释

此功能目前处于公开预览状态。 此预览版在没有服务级别协议的情况下提供,不建议用于生产工作负荷。 某些功能可能不受支持或者受限。 有关详细信息,请参阅 Microsoft Azure 预览版补充使用条款

本文提供有关在 Microsoft Fabric 中使用图形时可预测且高效地执行 GQL(图形查询语言)查询的指南。 这些建议基于当前平台行为和记录的约束。

有关图形大小、结果大小和查询超时的硬限制,请参阅 “当前限制”。

在模式初期进行筛选

将筛选器置于图形模式中,而不是放在后面的语句中。 模式级 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 *

注释

通过在图形建模过程中选择每个属性旁边的垃圾桶图标来删除未使用的属性。 每个节点的属性减少,可减少storage和查询开销。

限制结果集大小

查询可能具有较高基数的节点或关系时,应用 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 *

重要

graph 在可变长度模式中最多支持 8 个跃点 。 即便如此,也要使用您情境所允许的最紧密边界。 在此示例中,模式 {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 分钟超时限制相关的查询持续时间。