Spanner Graph 架构概览

借助 Spanner Graph,您可以将关联数据建模为属性图,该属性图以节点和边的网络形式表示信息。节点表示实体,边表示实体之间的连接。节点和边包含标签,用于将节点和边分类到集合中。节点和边还包括键值对形式的属性。

您可以通过将输入表中的行映射到图表节点和边缘来定义 Spanner Graph 架构。自定义节点和边缘的标签和属性,并了解架构更改如何影响图表依赖项。您还可以管理无架构数据,以实现更灵活的图表定义。

如需详细了解 Spanner Graph,请参阅 Spanner Graph 概览

了解属性图表数据模型

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

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

  • 标签,用于将节点和边分类到集合中,例如“city”
  • 属性,即键值对,例如“population”

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

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

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

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

每个有向边都表示一个单向关系,从来源节点流向目标节点。例如,Transfers 边缘将来源 Account 连接到目标 Account,从而表示资金流动。

Spanner Graph 架构概览图。

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

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

  • Person 节点包含以下属性:
    • name (STRING)
    • id (INT64)
  • Transfers 边缘包含以下属性:
    • amount (FLOAT64)

有向边缘和无向边缘

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

Spanner Graph 架构设计

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

在属性图表中定义节点

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

在以下示例中,您使用 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
  );

默认标签和属性

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

在上述示例中,

  • 每个 Account 节点都使用 Account 标签。
  • 每个 Account 节点都包含来自 Account 表列的 [id, create_time] 属性。

元素键

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

  • 默认情况下,元素键是输入表的主键。
  • 您可以使用 KEY 子句明确定义元素键。
  • 您可以将具有唯一索引限制条件的列用作元素键。

以下示例定义了 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 子句中。最简单的边缘定义形式仅包含输入表名称。Spanner Graph 会将输入表中的行映射到图表边缘。

来源节点和目标节点引用

在以下示例中,您将使用以下内容创建属性图表 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 标签。这两个定义都包含相同的一组属性名称 [id, name],并且具有相同的值类型。

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

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

以下语句会使 FinGraph 依赖于 Account 表以及 idcreate_time 列。

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

在此示例中,Spanner Graph 不允许进行以下架构更改:

  • 您无法舍弃 Account 表。为此,您需要移除 Account 节点定义。如需了解详情,请参阅移除现有节点或边缘定义
  • 您无法从 Account 表中删除 create_time 列。为此,您需要从 Account 节点定义中移除 create_time 属性。如需了解详情,请参阅更新现有节点或边缘定义

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

  • 如果其他架构要求允许,则修改 Account 表以及 idcreate_time 列架构。如需了解详情,请参阅更新架构

查看架构可视化图表

运行 Spanner Graph 查询后,您可以在 Spanner Studio 中查看架构的可视化图表。如需了解详情,请参阅使用 Spanner Graph 可视化图表

管理无架构数据

Spanner Graph 还支持无架构数据管理,这在需要更灵活的图表定义时非常有用。如需了解详情,请参阅在 Spanner Graph 中管理无架构数据

后续步骤