数据操纵语言最佳做法

本页面介绍使用数据操纵语言 (DML) 和分区 DML 的最佳做法。

使用 WHERE 子句缩小锁定范围

在读写事务中执行 DML 语句。当 Cloud Spanner 读取数据时,它会对其读取的有限范围的行获取共享读取锁定。具体而言,它仅会对您访问的列获取这些锁定。锁定可能包含与 WHERE 子句的过滤条件不匹配的数据。

当 Cloud Spanner 使用 DML 语句修改数据时,它会对您所修改的特定数据获取独占锁定。此外,它还会采用与读取数据时相同的方式获取共享锁定。如果您的请求包含大范围的行或整个表,则共享锁定可能会阻止其他事务并行完成。

为尽可能高效地修改数据,请使用 WHERE 子句,以使 Cloud Spanner 只读取必要的行。您可以通过按主键进行过滤或按二级索引的键进行过滤来实现此目标。WHERE 子句限制了共享锁定的范围,使 Cloud Spanner 能够更高效地处理更新。

例如,假设 Singers 表中的某位音乐人更改了其名字,则您需要在您的数据库中更新该名字。您可以执行以下 DML 语句,但该 DML 语句会强制 Cloud Spanner 扫描整个表,并获取共享锁定以覆盖整个表。因此,Cloud Spanner 必须读取数据超出需要的数据,因此并发事务不能并行修改数据:

-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards";

为使该更新更加高效,请在 WHERE 子句中添加 SingerId 列。SingerId 列是 Singers 表的唯一主键列:

-- RECOMMENDED: INCLUDING THE PRIMARY KEY COLUMN IN THE WHERE CLAUSE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards" AND SingerId = 1;

不要在同一事务中使用 DML 语句和变更

Cloud Spanner 可以在服务器端缓冲使用 DML 语句执行的插入、更新和删除,并且结果对同一事务中的后续 SQL 和 DML 语句可见。此行为与 Mutation API 不同,使用 Mutation API 时,Cloud Spanner 在客户端缓冲变更,并将变更作为提交操作的一部分发送至服务器端。因此,提交请求中的变更对同一事务中的 SQL 或 DML 语句不可见。

您可能希望在同一事务中组合 DML 语句和变更,因为某些操作仅受 Mutation API 支持。示例有 insert_or_update。如果事务在提交请求中同时包含 DML 语句和变更,则 Cloud Spanner 会在变更之前执行 DML 语句。为了避免在客户端库代码中考虑执行顺序,您应该在单个事务中使用 DML 语句或变更,但不要同时使用两者。如果同时使用两者,则应仅在事务的最后缓冲写入。

使用 PENDING_COMMIT_TIMESTAMP 函数写入提交时间戳

使用 PENDING_COMMIT_TIMESTAMP 函数在 DML 语句中写入提交时间戳。Cloud Spanner 会在事务提交时选择提交时间戳。

分区 DML 以及日期和时间戳函数

分区 DML 使用可能在不同时间运行和提交的一个或多个事务。如果使用日期时间戳函数,则修改的行可能包含不同的值。

使用批处理 DML 在一个请求中发送多个 DML。

使用批处理 DML 在一个请求中发送多个 DML。这样,只需要一次客户端-服务器往返,从而减少了延迟时间。