排查 Spanner Graph 问题

本文档介绍了您在使用 Spanner 图表时可能会遇到的错误。还提供了错误示例和推荐的修复方法。

如果您在查看此问题排查指南后需要进一步的支持,请参阅获取支持

架构错误

架构结果基于设置和查询 Spanner Graph 中使用的相应数据集。

元素键必须保证唯一性

错误消息

Neither the primary keys nor any unique index defined on the property graph element source table `Person` provides the uniqueness guarantee for graph element `Person` belonging to the graph `FinGraph`. You want to redefine the element key columns (`name`) based on the source table's primary keys, or create a unique index on the element's key columns.

错误示例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (name)
  );

在元素键列上创建唯一索引,并根据源表主键重新定义元素键列。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (id)
  );

或者,您也可以在元素键列上创建唯一索引。

CREATE UNIQUE INDEX PersonNameIndex ON Person(name);
CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (name)
  );

元素定义的名称必须是唯一的

错误消息

Account is defined more than once; use a unique name.

错误示例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account,
    Person
  )
  EDGE TABLES (
    Account
      SOURCE KEY(owner_id) REFERENCES Person
      DESTINATION KEY(account_id) REFERENCES Account
  );

为边定义使用一个唯一的名称。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account,
    Person
  )
  EDGE TABLES (
    Account AS Owns
      SOURCE KEY(owner_id) REFERENCES Person
      DESTINATION KEY(account_id) REFERENCES Account
  );

属性的标签定义必须保持一致

错误消息

The label Entity is defined with different property declarations. There is one instance of this label defined with properties of [id]. Another instance is defined with properties of [name].

错误示例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person LABEL Entity PROPERTIES (name),
    Account LABEL Entity PROPERTIES (id)
  );

您必须在同一标签下使用同一组属性名称。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person LABEL Entity PROPERTIES (id, name),
    Account LABEL Entity PROPERTIES (id, name)
  );

属性声明必须与属性类型保持一致

错误消息

The property declaration of name has type conflicts. There is an existing declaration of type INT64. There is a conflicting one of type STRING.

错误示例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person PROPERTIES (name),
    Account PROPERTIES (id AS name)
  );
CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person PROPERTIES (name),
    Account PROPERTIES (CAST(id AS STRING) AS name)
  );

属性定义不得是子查询

错误消息

Property value expression of count cannot contain a subquery.

错误示例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person PROPERTIES ((SELECT COUNT(*) FROM Person) AS count)
  );

N/A。不允许这种情况。

同一元素定义中的属性定义必须一致

错误消息

Property location has more than one definition in the element table Person

错误示例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person
      LABEL Person PROPERTIES (country AS location)
      LABEL Entity PROPERTIES (city AS location)
  );

使用相同的媒体资源定义。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person
      LABEL Person PROPERTIES (country AS location)
      LABEL Entity PROPERTIES (country AS location)
  );

或者,分配不同的属性名称。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person
      LABEL Person PROPERTIES (country AS location)
      LABEL Entity PROPERTIES (city AS city)
  );

查询错误

查询结果基于设置和查询 Spanner Graph 中使用的相应数据集。

图表元素无法作为查询结果返回

错误消息

Returning expressions of type GRAPH_ELEMENT is not allowed

错误示例

GRAPH FinGraph
MATCH (n:Account)
RETURN n;
GRAPH FinGraph
MATCH (n:Account)
RETURN TO_JSON(n) AS n;

属性规范不能与 WHERE 子句搭配使用

错误消息

WHERE clause cannot be used together with property specification

错误示例

GRAPH FinGraph
MATCH (n:Account {id: 1} WHERE n.is_blocked)
RETURN n.id;

您可以使用以下某种建议的解决方法。

GRAPH FinGraph
MATCH (n:Account {id: 1})
WHERE n.is_blocked
RETURN n.id;
GRAPH FinGraph
MATCH (n:Account WHERE n.id = 1 AND n.is_blocked )
RETURN n.id;
GRAPH FinGraph
MATCH (n:Account {id: 1, is_blocked: TRUE})
RETURN n.id;

不允许引用之前语句中定义的变量

错误消息

Name 'account_id', defined in the previous statement, can only be referenced in the outermost WHERE clause of MATCH

说明

MATCH 模式中不允许引用之前语句中定义的变量。在图查询中,之前语句定义的名称只能在 MATCH 的最外层 WHERE 子句中使用。

错误示例
GRAPH FinGraph
LET account_id = 1
MATCH (n:Account {id: account_id})
RETURN n.id;
GRAPH FinGraph
LET account_id = 1
MATCH (n:Account)
WHERE n.id = account_id
RETURN n.id;

不允许重新定义相关图表变量

错误消息

The name account is already defined; redefining graph element variables in a subquery is not allowed. To refer to the same graph element, use a different name and add an explicit filter that checks for equality.

说明

在图表查询中,无法在内部图表子查询中重新定义图表元素名称。此场景可能会被解读为引用与外部作用域相同的图元素,或绑定到会掩盖外部作用域名称的新图元素。不允许重新定义。

错误示例

GRAPH FinGraph
MATCH (account:Account)
RETURN account.id AS account_id, VALUE {
  MATCH (account:Account)-[transfer:Transfers]->(:Account)
  RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;
GRAPH FinGraph
MATCH (account:Account)
RETURN account.id AS account_id, VALUE {
  MATCH (a:Account)-[transfer:Transfers]->(:Account)
  WHERE a = account
  RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;

查询语义问题

查询结果基于设置和查询 Spanner Graph 中使用的相应数据集。

不同的 WHEREFILTER 会产生不同的输出

说明

FILTER 是语句;WHEREMATCHOPTIONAL MATCH 语句的一部分,属于子句。

在第一个示例中,WHERE 子句会向 OPTIONAL MATCH 语句中描述的模式添加其他约束条件。这不是匹配完成后的过滤条件。

在第二个示例中,FILTER 语句是匹配完成后的过滤条件。

示例问题

以下示例的输出不同,因为 WHEREFILTER 不同。

示例 1

GRAPH FinGraph
MATCH (n:Account {id: 7})
OPTIONAL MATCH (m:Account)
WHERE FALSE
RETURN n.id AS n_id, m.id AS m_id;
n_id m_id
7 null

示例 2

GRAPH FinGraph
MATCH (n:Account {id: 7})
OPTIONAL MATCH (m:Account)
FILTER FALSE
RETURN n.id AS n_id, m.id AS m_id;

空白结果。

在语句中传播不同的变量会导致不同的输出

说明

在图表查询语言中,多次声明的变量在所有出现位置都指同一图表元素。

在示例 1 中,没有 Account 节点的 id 同时为 716。因此,系统会返回空结果。

在示例 2 中,前一个语句不会返回名称 n(只会返回 id)。因此,第二个 MATCH 会找到 id16Account 节点。

示例问题

以下示例的输出不同,因为不同的变量会传播到各个语句。

示例 1

GRAPH FinGraph
MATCH (n:Account {id: 7})
RETURN n

NEXT

MATCH (n:Account {id: 16})
RETURN n.id AS n_id;

空白结果。

示例 2

GRAPH FinGraph
MATCH (n:Account {id: 7})
RETURN n.id AS id

NEXT

MATCH (n:Account {id: 16})
RETURN n.id AS n_id;
n_id
16

如果后续语句不是 LIMIT,系统会忽略 ORDER BY

说明

在图查询语言中,除非满足以下条件之一,否则系统会忽略 ORDER BY 语句:

  • ORDER BY 是最后一个语句。
  • ORDER BY 紧随 LIMIT 之后。

在示例 1 中,LIMIT 不是紧随 ORDER BY 之后;最后一个 LIMIT 是分开的。这意味着引擎会忽略 ORDER BY

在示例 2 中,ORDER BY 适用,因为 LIMIT 紧随 ORDER BY 之后。

示例问题

以下示例的输出不同,因为在示例 1 中,如果 ORDER BY 语句未与 LIMIT 搭配使用,系统会忽略该语句。

示例 1

GRAPH FinGraph
MATCH (n:Account)
ORDER BY n.id DESC
RETURN n.id
LIMIT 3;
n_id
7

示例 2

GRAPH FinGraph
MATCH (n:Account)
ORDER BY n.id DESC
LIMIT 3
RETURN n.id;
n_id
20

不同的边缘模式会产生不同的输出

说明

在错误示例中使用的数据集中,ANY 方向边缘模式会与图中的每个 Transfers 边缘匹配两次。

在示例 1 中,从 Account(id=x)Account(id=y)Transfers 边可以匹配两次,如下所示:

  • n= Account(id=x), m= Account(id=y)
  • n= Account(id=y), m= Account(id=x)

示例 2 中只有一个匹配,其中 n=Account(id=x) 且 m=Account(id=y)

因此,示例 1 中的查询会返回 10,示例 2 中的查询会返回 5

示例问题

以下示例的输出不同,因为使用了不同的边缘模式。

示例 1

GRAPH FinGraph
MATCH (n:Account)-[:Transfers]-(m:Account)
RETURN COUNT(*) AS num_transfer_edges;
num_transfer_edges
10

示例 2

GRAPH FinGraph
MATCH (n:Account)-[:Transfers]->(m:Account)
RETURN COUNT(*) AS num_transfer_edges;
num_transfer_edges
5

更改错误

更新结果基于设置和查询 Spanner Graph 中使用的数据集。

缺少来源节点违反外键约束条件

错误消息

Parent row for row [...] in table AccountTransferAccount is missing. Row cannot be written.

说明

AccountTransferAccount 边表是 INTERLEAVED INTO PARENT Account node 表。如需创建 Transfer 边,其父 Account 节点必须已存在。

错误示例

INSERT INTO AccountTransferAccount (id, to_id, create_time, amount)
VALUES (100, 1, PENDING_COMMIT_TIMESTAMP(), 200);

先创建前置的 Account 节点,然后创建 Transfer 边。

缺少目标节点违反外键约束条件

错误消息

Foreign key constraint FK_TransferTo is violated on table AccountTransferAccount. Cannot find referenced values in Account(id)

说明

AccountTransferAccount 表通过名为 FK_TransferToForeignKey 引用 Accounttable。如需创建 Transfer 边,引用的尾随节点 Account 节点必须已存在。

错误示例

INSERT INTO AccountTransferAccount (id, to_id, create_time, amount)
VALUES (1, 100, PENDING_COMMIT_TIMESTAMP(), 200);

先创建尾随账号节点,然后创建 Transfer 边。

孤立的出边违反了父子关系

错误消息

Integrity constraint violation during DELETE/REPLACE. Found child row [...] in table AccountTransferAccount

说明

AccountTransferAccount 边表是 INTERLEAVED INTO PARENT Account 节点表,并且要删除的 Account 节点仍附有出边。

错误示例

DELETE FROM Account WHERE id = 1;

请先删除所有出站 Transfer 边,然后再删除 Account 节点。或者,为 INTERLEAVE 定义 ON DELETE CASCADE,并让 Spanner 自动删除这些边。

孤立的入边违反了父子关系

错误消息

Foreign key constraint violation when deleting or updating referenced row(s): referencing row(s) found in table AccountTransferAccount

说明

AccountTransferAccount 边表通过 ForeignKey 引用 Account 节点表,并且要删除的 Account 节点仍附有入边。

错误示例

DELETE FROM Account WHERE id = 1;

请先删除所有传入的 Transfer 边,然后再删除 Account 节点。或者,为 ForeignKey 定义 ON DELETE CASCADE,并让 Spanner 自动删除这些边。