Spanner Graph 架构概览

本文档介绍了 Spanner 图架构,并提供了示例来说明关键概念。如需详细了解 Spanner Graph,请参阅 Spanner Graph 概览

属性图数据模型

借助属性图,您可以对关联的数据进行建模。它将信息表示为节点和边的网络。节点表示数据环境中的实体,例如客户、产品或地点。边表示这些节点之间的连接,描述“已购买”“关注”或“位于”等关系。

节点和边都可以包含以下信息:

  • 标签,用于将节点和边分类到集合中,例如城市
  • 属性,即键值对,例如人口

图 1 中的示例展示了如何设计图表来对财务活动进行建模。此图包含以下类型的以节点形式建模的实体:

  • 个人:表示参与金融交易的个人。
  • 账号:表示用于交易的银行账户。

这些实体通过不同类型的关系相连,这些关系由以下有向边表示:

  • 拥有:个人拥有一个或多个账号。
  • 转账:资金从一个账户转移到另一个账户。

每个有向边都表示从源节点流向目的节点的单向关系。例如,Transfers 边将源 Account 连接到目的地 Account,表示资金流向。

Spanner Graph 架构概览图。

图 1. 包含多个节点和有向边的图示例。

节点和边可以在属性中包含其他信息。每个属性都有一个名称和一个值。

  • Person 节点具有以下属性:
    • nameSTRING
    • idINT64
  • 转移边具有以下属性:
    • amount (FLOAT64)

有向边和无向边

示例图表使用有向边,用于指明实体之间关系的特定方向。不过,某些关系(例如社交网络中的好友关系)是无向的,它们表示没有明确起点或终点的互惠连接。在这种情况下,您可以将无向边建模为两个有向边,每个方向一个边。

Spanner Graph 架构设计

借助 Spanner Graph,您可以使用 CREATE PROPERTY GRAPH 语句根据表创建图。用于创建图表的表格称为输入表格。此方法基于 SQL/PGQ(属性图查询),该方法是 SQL:2023 标准的一部分。

在属性图中定义节点

如需定义节点,请在 NODE TABLES 子句中添加节点定义。最简单的节点定义形式仅包含输入表名称。输入表中的行会映射到图节点。

在以下示例中,您使用 NODE TABLES 子句在 FinGraph 属性图中定义 Account 节点。节点定义包含输入表 Account

-- First, create an Account table.
CREATE TABLE Account (
  id           INT64 NOT NULL,
  create_time  TIMESTAMP,
) PRIMARY KEY (id);

-- Next, use the Account table as input table of Account node definition.
CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account
  );

默认标签和属性

默认情况下,所有节点都使用输入表名称作为标签,并且输入表中的所有列都会作为节点属性公开。

在前面的示例中,

  • 每个账号节点都有 Account 标签。
  • 每个账号节点都有从 Account 表列创建的属性 [id, create_time]

元素键

节点定义还定义了元素键,该键用于唯一标识图节点。

  • 默认情况下,元素键是输入表的主键。
  • 元素键可以通过 KEY 子句明确定义。
  • 具有唯一性约束条件 UNIQUE INDEX 的列可以用作元素键。

以下示例定义了 Account 节点和 Person 节点。

  • 默认情况下,Account 节点使用 Account 表的主键作为其元素键。
  • 另一方面,Person 节点使用 KEY 子句明确指定 id 作为元素键。
CREATE TABLE Person (
  id           INT64 NOT NULL,
  name         STRING(MAX),
) PRIMARY KEY (id);

CREATE TABLE Account (
  id           INT64 NOT NULL,
  create_time  TIMESTAMP,
) PRIMARY KEY (id);

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (id),
    Account
  );

将输入表中的行映射到图表中的节点

  • 具有非 null 元素键的每一行都会映射到图中的一个唯一节点(由元素键标识)。
  • 系统会忽略元素键为 null 的行。

在属性图中定义边

如需定义边,请将边定义添加到 EDGE TABLES 子句中。最简单的边定义形式仅包含输入表名称。输入表中的行会映射到图边。

来源和目标节点引用

在以下示例中,您将使用以下内容创建属性图 FinGraph

  • PersonAccount 节点
  • PersonOwnAccount 边缘
CREATE TABLE Person (
 id            INT64 NOT NULL,
 name          STRING(MAX),
) PRIMARY KEY (id);

CREATE TABLE Account (
 id            INT64 NOT NULL,
 create_time   TIMESTAMP,
) PRIMARY KEY (id);

CREATE TABLE PersonOwnAccount (
 id            INT64 NOT NULL,
 account_id    INT64 NOT NULL,
 create_time   TIMESTAMP,
 FOREIGN KEY (account_id) REFERENCES Account (id)
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person;

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person,
    Account
  )
  EDGE TABLES (
    PersonOwnAccount
      SOURCE KEY (id) REFERENCES Person (id)
      DESTINATION KEY (account_id) REFERENCES Account (id)
  );

边定义必须使用 SOURCE KEYDESTINATION KEYREFERENCES 子句定义源节点和目标节点引用。以下示例使用 PersonOwnAccount 的边定义来说明此概念:

EDGE TABLES (
  PersonOwnAccount
    SOURCE KEY (id) REFERENCES Person (id)
    DESTINATION KEY (account_id) REFERENCES Account (id)
)

每个 PersonOwnAccount 边都会将 Person(源)节点连接到 Account(目的地)节点。

  • 边的源节点是 Person 节点,其 id 与边 id 相同。
  • 边的目标节点是 Account 节点,其 id 与边 account_id 相同。

此外,对于 PersonOwnAccount 边,以下为真:

  • 元素键是 PersonOwnAccount 表的主键,即 (id, account_id)
  • 每个边都具有与 PersonOwnAccount 表中的列相同的一组属性。
  • 每个边都有默认的 PersonOwnAccount 标签。

将边输入表中的行映射到图表中的边

  • 边输入表中元素键不为 null 的每一行通常会映射到图表中的一个唯一边。
  • 一行可能与图表中的零个或多个边对应,例如,当来源节点引用与来源节点表中的零个或多个节点匹配时。
  • 您可以在不同的节点或边定义中使用相同的输入表,以创建不同的节点或边集。如需了解详情,请参阅合并节点和边输入表

自定义标签和属性

您可以使用 LABELPROPERTIES 子句自定义标签和属性。

在以下示例中,定义了两个节点,即 PersonAccount

  • Person 节点通过标签 Customer 公开 address 属性。address 属性由表达式 CONCAT(city, ", ", country), 定义,该表达式引用输入表 Person 中的 citycountry 列。
  • 对于 AccountAccount 节点通过标签 Account 公开 idcreate_time 属性。
  • PersonAccount 具有 Entity 标签,其中包含属性 [id, name]。
    • 对于 Personidname 属性来自输入表列。
    • 对于 Accountname 属性引用输入表的 nick_name 列。
CREATE TABLE Person (
 id               INT64 NOT NULL,
 name             STRING(MAX),
 birthday         TIMESTAMP,
 country          STRING(MAX),
 city             STRING(MAX),
) PRIMARY KEY (id);

CREATE TABLE Account (
 id               INT64 NOT NULL,
 create_time      TIMESTAMP,
 is_blocked       BOOL,
 nick_name        STRING(MAX),
) PRIMARY KEY (id);

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (id)
      LABEL Customer
        PROPERTIES (CONCAT(city, ", ", country) AS address)
      LABEL Entity PROPERTIES (id, name),
    Account KEY (id)
      LABEL Account PROPERTIES (id, create_time)
      LABEL Entity PROPERTIES (id, nick_name AS name)
  );

标签和房源一致性

在图表中,标签和属性通过其名称进行唯一标识。同名标签和属性可以在多个节点或边定义中出现。不过,同名标签和房源必须遵循以下规则:

  • 具有相同名称的属性必须具有相同的值类型。
  • 同名标签必须公开相同的属性列表。

在前面的示例中,PersonAccount 节点中都定义了 Entity 标签。在这两种定义中,它们具有一组具有相同值类型的属性名称 [idname]。

图表与其他架构对象之间的依赖关系

CREATE PROPERTY GRAPH 创建的图表依赖于其他架构对象,例如节点和边定义的输入表,以及属性引用的表列。如果架构更改会破坏其中一个依赖项,则不允许进行更改。

以下语句会创建 FinGraphAccount 表以及 idcreate_time 列之间的依赖项。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account PROPERTIES (id, create_time)
  );

以下是您不允许进行的架构更改示例:

  • 删除 Account 表,除非您先移除 Account 节点定义。如需了解详情,请参阅移除现有节点或边定义
  • Account 表中删除 create_time 列,除非您先从 Account 节点定义中移除 create_time 属性。如需了解详情,请参阅更新现有节点或边定义

不过,您可以进行以下架构更改:

  • 修改 Account 表以及 idcreate_time 列架构,前提是其他架构要求允许这样做。如需了解详情,请参阅进行架构更新

后续步骤