删除父表的1行时的扳手突变限制

时间:2020-06-23 14:00:01

标签: google-cloud-spanner

Spanner documentation says

  1. 插入和更新操作计入它们影响的列数的倍数。例如,如果将值插入五列,则插入新记录可算作五个突变。无论受影响的列数如何,删除和删除范围操作都视为一种突变。从父表中删除具有ON DELETE CASCADE批注的行也视为一个突变,而不管存在的交错子行的数量如何。

今天,我试图从其子表(交错表)指定为ON DELETE CASCADE的父表中删除1行。

示例:DELETE FROM my_table WHERE some_primary_key='somevalue'

我收到一条错误消息,说我正在达到突变限制,因为在此拆分中,子表的行数超过了2万。根据上面的记录,无论子表中有多少行,仍应视为1个突变。

请注意,子表具有辅助索引设置。

此文档是否存在问题,或者我缺少什么?

1 个答案:

答案 0 :(得分:3)

似乎随后的每次索引更新都算作一个突变。我做了以下实验来验证它:

  1. 创建表格
CREATE TABLE ParentTable (
    Pid INT64 NOT NULL,
    Data STRING(1024),
) PRIMARY KEY(Pid);

CREATE TABLE ChildTable (
    Pid INT64 NOT NULL,
    Cid INT64 NOT NULL,
    Data STRING(1024),
) PRIMARY KEY(Pid, Cid),
  INTERLEAVE IN PARENT ParentTable ON DELETE CASCADE;
  1. 填充1个父行和30000个子行:
// Inserts 1 ParentTable rows
INSERT INTO ParentTable (Pid) (SELECT * FROM UNNEST([1]));

// Insert 30000 rows to ChildTable for pid=1
INSERT INTO ChildTable (Pid, Cid) (SELECT 1, child.Cid FROM 
(SELECT 0+G.g AS Cid FROM (SELECT E.e*10+F.f AS g FROM (SELECT C.c*10+D.d AS e FROM (SELECT A.a*10 + B.b AS c FROM (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS a) AS A, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS b) AS B) AS C, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS d) AS D) AS E, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) as f) AS F) AS G) AS Child);

INSERT INTO ChildTable (Pid, Cid) (SELECT 1, child.Cid FROM 
(SELECT 10000+G.g AS Cid FROM (SELECT E.e*10+F.f AS g FROM (SELECT C.c*10+D.d AS e FROM (SELECT A.a*10 + B.b AS c FROM (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS a) AS A, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS b) AS B) AS C, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS d) AS D) AS E, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) as f) AS F) AS G) AS Child);

INSERT INTO ChildTable (Pid, Cid) (SELECT 1, child.Cid FROM 
(SELECT 20000+G.g AS Cid FROM (SELECT E.e*10+F.f AS g FROM (SELECT C.c*10+D.d AS e FROM (SELECT A.a*10 + B.b AS c FROM (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS a) AS A, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS b) AS B) AS C, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) AS d) AS D) AS E, (SELECT * FROM UNNEST([0,1,2,3,4,5,6,7,8,9]) as f) AS F) AS G) AS Child);
  1. 验证子表是否具有30000行且Pid = 1:
// Verify counts
SELECT COUNT(*) FROM ChildTable WHERE Pid=1;
  1. 尝试删除它(成功)
DELETE FROM ParentTable WHERE Pid=1
  1. 现在再次重复1到3。这次我们在子表上创建二级索引
CREATE INDEX Cid_Increasing ON ChildTable (Cid) STORING (Data);
  1. 尝试再次删除父行,但这一次失败了
This DML statement exceeds the mutation limit for a single transaction (20000). To reduce the mutation count, try a transaction with fewer writes, or use fewer indexes. This can help because the mutation count for an operation is equal to the number of columns it affects. Reducing writes or indexes reduces the number of affected columns, bringing your mutation count under the limit. Alternatively, try a Partioned DML statement using the client libraries or gcloud command-line tool.
  1. 好的,尝试将行数减少到20000,然后删除。再次失败。
DELETE FROM ChildTable WHERE Cid > 19999; // deleted 10000 rows.
SELECT COUNT(*) FROM ChildTable WHERE Pid=1; // should be 20000 now.
DELETE FROM ParentTable WHERE Pid=1; // still failed.
  1. 删除子表中的另一行。这次父级删除成功。
DELETE FROM ChildTable WHERE Cid > 19998;
SELECT COUNT(*) FROM ChildTable WHERE Pid=1; // should be 19999 now.
DELETE FROM ParentTable WHERE Pid=1; // succeeded 

最后两个实验表明:

  1. 父行删除及其子行删除仅计为1个突变。
  2. 随后的每次索引更改都计为1个突变。