删除 1 行 parent table 的 Spanner 突变限制
Spanner mutation limit on deleting 1 row of parent table
- Insert and update operations count with the multiplicity of the number of columns they affect. For example, inserting a new record may count as five mutations, if values are inserted into five columns. Delete and delete range operations count as one mutation regardless of the number of columns affected. Deleting a row from a parent table that has the ON DELETE CASCADE annotation is also counted as one mutation regardless of the number of interleaved child rows present.
今天我试图从 parent table 中删除 1 行,其 child(交错)table 指定了 ON DELETE CASCADE
。
示例:DELETE FROM my_table WHERE some_primary_key='somevalue'
我收到错误消息说我正在达到突变限制,因为 child table 在这个拆分中有超过 20k 行。根据上面的文档,无论 child table.
中有多少行,仍应算作 1 个突变
请注意 child table 有二级索引设置。
此文档是否有问题,或者我遗漏了什么?
似乎每次后续索引更新都算作一个突变。我做了以下实验来验证它:
- 创建一个table
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 parent 行和 30000 child 行:
// 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);
- 验证 child table 有 30000 行 Pid=1:
// Verify counts
SELECT COUNT(*) FROM ChildTable WHERE Pid=1;
- 尝试删除(成功)
DELETE FROM ParentTable WHERE Pid=1
- 现在再重复1到3。这次我们在 child table
上创建二级索引
CREATE INDEX Cid_Increasing ON ChildTable (Cid) STORING (Data);
- 再次尝试删除parent行,这次失败说
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.
- 好的,尝试将行数减少到 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.
- 在 child table 中再删除一行。这次parent删除成功
DELETE FROM ChildTable WHERE Cid > 19998;
SELECT COUNT(*) FROM ChildTable WHERE Pid=1; // should be 19999 now.
DELETE FROM ParentTable WHERE Pid=1; // succeeded
最后两个实验表明:
- parent 行删除及其 child 行删除仅计为 1 个突变。
- 每个后续索引更改都计为 1 个突变。
- Insert and update operations count with the multiplicity of the number of columns they affect. For example, inserting a new record may count as five mutations, if values are inserted into five columns. Delete and delete range operations count as one mutation regardless of the number of columns affected. Deleting a row from a parent table that has the ON DELETE CASCADE annotation is also counted as one mutation regardless of the number of interleaved child rows present.
今天我试图从 parent table 中删除 1 行,其 child(交错)table 指定了 ON DELETE CASCADE
。
示例:DELETE FROM my_table WHERE some_primary_key='somevalue'
我收到错误消息说我正在达到突变限制,因为 child table 在这个拆分中有超过 20k 行。根据上面的文档,无论 child table.
中有多少行,仍应算作 1 个突变请注意 child table 有二级索引设置。
此文档是否有问题,或者我遗漏了什么?
似乎每次后续索引更新都算作一个突变。我做了以下实验来验证它:
- 创建一个table
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 parent 行和 30000 child 行:
// 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);
- 验证 child table 有 30000 行 Pid=1:
// Verify counts
SELECT COUNT(*) FROM ChildTable WHERE Pid=1;
- 尝试删除(成功)
DELETE FROM ParentTable WHERE Pid=1
- 现在再重复1到3。这次我们在 child table 上创建二级索引
CREATE INDEX Cid_Increasing ON ChildTable (Cid) STORING (Data);
- 再次尝试删除parent行,这次失败说
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.
- 好的,尝试将行数减少到 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.
- 在 child table 中再删除一行。这次parent删除成功
DELETE FROM ChildTable WHERE Cid > 19998;
SELECT COUNT(*) FROM ChildTable WHERE Pid=1; // should be 19999 now.
DELETE FROM ParentTable WHERE Pid=1; // succeeded
最后两个实验表明:
- parent 行删除及其 child 行删除仅计为 1 个突变。
- 每个后续索引更改都计为 1 个突变。