SonnetDB Graph Beta 查询:SQL/PGQ、受限 GQL 风格与 EXPLAIN
SonnetDB Graph Beta 查询:SQL/PGQ、受限 GQL 风格与 EXPLAIN
SonnetDB 的原生属性图目前是 Graph Beta;本文介绍如何用 SQL/PGQ GRAPH_TABLE 与嵌入式受限 GQL 风格查询一跳或有界路径,并用 EXPLAIN 检查实际访问路径、预算和拒绝边界。

AI 主题示意图,并非实测截图。
本文按本地源码提交 dbc8178988a0293ed67d24e6f70b78b970465aa0 和 Graph 专题合同核对。GitHub 当前正式 Release 是 v4.0.0,但本文所述较新的 Graph Beta 合同应先按源码提交、目标包与实际 Server 分别核验,不能从本文或本地回归推断已在所有发行物、远程服务或固定硬件上验收。
1. 先选对入口
Graph Beta 有两个查询写法,但它们不是两套不同的存储或权限通道:
| 入口 | 适合的场景 | 关键限制 |
|---|---|---|
SQL/PGQ GRAPH_TABLE |
Server、HTTP、ADO.NET、Studio 和连接器 | 继续使用既有 SQL 数据面和权限边界 |
SqlExecutor.ExecuteGql |
显式 opt-in 的嵌入式 .NET 调用 | 不是新的 wire endpoint,也不是 DDL/DML 通道 |
EXPLAIN [ANALYZE] |
复核计划、统计新鲜度与运行计数 | 普通 EXPLAIN 不为估算扫描业务数据 |
受限 GQL 风格入口会解析为既有 SelectStatement 和 GraphTableSource,再走与 SQL/PGQ 相同的成本规划、原生 adjacency 或关系映射 accessor、预算和执行器。因此,同一个 MATCH 不应通过字符串拼接在两条线路上制造不同的安全或结果语义。
2. 从 SQL/PGQ 开始写一跳查询
关系映射图可以使用 catalog 中声明的 label 名;原生图使用正整数 label ID。请在隔离的示例数据库中逐条执行以下建图与写入语句;它们会写数据,不要对已有同名业务图重复运行。
CREATE GRAPH topology;
INSERT INTO GRAPH topology VERTEX (id, labels, property_7)
VALUES (42, 1, 'pump'), (43, 1, 'valve');
INSERT INTO GRAPH topology EDGE (id, source_id, target_id, label_id)
VALUES (100, 42, 43, 2);
下面把 @anchor 绑定为 Int64 值 42,取得一跳关系的稳定输出名;预期一行是 42, 43, 100。支持参数的调用方式见下一节,纯 SQL 控制台也可在这个固定示例中将参数写成字面量 42。
SELECT source_id, target_id, edge_id
FROM GRAPH_TABLE (
topology
MATCH (a IS 1)-[e IS 2]->(b IS 1)
WHERE a.id = @anchor
COLUMNS (a.id AS source_id, b.id AS target_id, e.id AS edge_id)
)
ORDER BY edge_id
LIMIT 10;
这个例子表达的是一个 pattern、两个 vertex 变量和一个 edge 变量。固定一跳可省略 hop 范围;可变路径必须满足 1 <= min <= max <= 64。方向还可写为入向或无向模式,但不要把这一有限语法误解为完整 Cypher 或 ISO GQL。
查询前请先明确结果预算和读者真正需要的列。LIMIT 约束的是返回结果,不会自动证明整个执行链路在任意负载下流式、无界内存或具备生产容量。原生图和关系映射图都可能使用索引 seek 或有界 scan fallback;应以计划输出而不是名称猜测为准。
3. 嵌入式 GQL 风格入口如何等价执行
嵌入式程序可用 SqlParameters 传入参数,再显式调用 ExecuteGql。下面的 USE GRAPH 写法与上一节 SQL/PGQ 查询生成相同的 Graph AST、计划和结果;它没有绕过 SQL 参数绑定。
using SonnetDB.Engine;
using SonnetDB.Sql;
using SonnetDB.Sql.Execution;
// 此目录须是已按上一节创建示例图的独立数据库目录。
using var db = Tsdb.Open(new TsdbOptions { RootDirectory = @"D:\sonnetdb-examples\graph-query" });
var parameters = new SqlParameters().AddNamed("anchor", 42L);
SelectExecutionResult result = SqlExecutor.ExecuteGql(
db,
"""
USE GRAPH topology
MATCH (a IS 1)-[e IS 2]->(b IS 1)
WHERE a.id = @anchor
RETURN a.id AS source_id, b.id AS target_id, e.id AS edge_id
ORDER BY edge_id
LIMIT 10
""",
parameters);
GqlParser.Parse 可单独返回现有 SQL typed AST。EXPLAIN 或 EXPLAIN ANALYZE 应放在 USE GRAPH 前,返回的字段仍与等价 GRAPH_TABLE 查询相同,而不是新增一个只对 GQL 生效的计划格式。
4. 用 EXPLAIN 验证访问策略,而不是猜测性能
Graph SQL V1 为每个 label 和每个非空 property 维护自动等值派生索引。对于形如 variable.property_<id> = scalar 的谓词,graph_cost_v1 会比较两侧 value cardinality,并编译为已有的 property seek;没有统计时仍可使用该索引,但估算是有界启发式。非等值或不支持的谓词会回退 label index 并保留残余过滤。
可从计划中查看以下信息:
EXPLAIN ANALYZE
SELECT source_id, target_id
FROM GRAPH_TABLE (
topology
MATCH (a IS 1)-[e IS 2]->(b IS 1)
WHERE a.property_7 = 'pump'
COLUMNS (a.id AS source_id, b.id AS target_id)
);
计划会报告 anchor_side、anchor_access_path、anchor_property_id、statistics_sequence、statistics_freshness、estimate_source、edge_access_path 和 fallback_reason。使用 ANALYZE 后还会给出实际 anchor 路径、rows、expansions、frontier 与 elapsed。属性 seek 后仍执行完整 MATCH 谓词,所以优化只能改变候选获取方式,不能改变查询语义。
ANALYZE GRAPH <name> 的统计属于可重建内存状态:重开后是 missing,后续写入会使它变为 stale。因此“有索引”不等于“统计永远新鲜”,更不等于固定硬件上的吞吐或延迟承诺。
5. 明确会被拒绝的形状
当前受限入口有意拒绝以下写法或能力:
RETURN *、重名输出而没有AS别名、多语句输入;- 多 pattern、
OPTIONAL MATCH、UNION、GROUP BY; - Cypher 的
:Label、MERGE、WITH、UNWIND、CALL; - GQL DDL/DML、完整 ISO GQL、Bolt 与分布式图协议;
- 把
CREATE/DROP PROPERTY INDEX当作 V1 的命名或范围/复合/partial 索引接口。
图的创建和 mutation 仍走现有 Graph API 或 SQL,并遵守原有权限与乐观版本合同。Graph SQL V1 的 UPDATE/DELETE 需要且只能用 id 与 element_version 的等值条件;跨 graph/关系表原子事务、无版本 last-write-wins、DETACH DELETE 也不属于本文的支持范围。
6. 交付前检查清单
- 对远程、ADO.NET、Studio 或连接器优先写等价 SQL/PGQ
GRAPH_TABLE,并使用参数而非拼接用户输入。 - 对嵌入式调用才使用显式
ExecuteGql;将EXPLAIN的访问路径和 fallback 原因随诊断记录保存。 - 将
LIMIT、hop 上限和查询预算当作合同的一部分;超出支持矩阵时拆为已支持的 SQL 派生表,或在应用端显式组合。 - 在变更数据后重新审视统计状态;将
missing/stale写入诊断,而不是把旧估算当作实时事实。
Graph Beta 已有原生邻接、SQL/PGQ、受限嵌入式 GQL 风格入口和自动回归,但固定目标硬件、LDBC/Graphalytics、七天 mixed workload、恢复和发布门禁仍未闭环。本文示例按当前 API 与测试源码静态复核,未在本次写作中实际执行;本文没有运行真实 Server、远程连接、LDBC、固定硬件、容量、长期负载或生产验证。
参考
关注我们,扫码进群沟通
欢迎关注我们,扫码加入微信或 QQ 交流群,一起交流技术实践,分享使用经验和问题反馈。
微信交流二维码

QQ 交流群:IoTSharp,群号 63631741

请扫码并关注我们,进群沟通。若二维码暂时无法使用,可通过 QQ 群号 63631741 搜索加入。

浙公网安备 33010602011771号