本页面介绍了如何为在 PostgreSQL 方言数据库中使用 Spanner 执行的每个插入和更新操作写入提交时间戳。
插入提交时间戳
基于 TrueTime 技术的提交时间戳是在数据库中提交事务的时间。您可以以原子方式将事务的提交时间戳存储到列中。借助存储在表中的提交时间戳,您可以确定变更的确切顺序并构建更改日志等功能。
要在数据库中插入提交时间戳,请完成以下步骤:
创建类型为
SPANNER.COMMIT_TIMESTAMP的列。例如:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;如果要使用 DML 执行插入或更新操作,请使用
SPANNER.PENDING_COMMIT_TIMESTAMP()函数来写入提交时间戳。如果要使用预处理语句或变更执行插入或更新操作,请为提交时间戳列使用占位符字符串
SPANNER.COMMIT_TIMESTAMP()。您还可以使用客户端库提供的提交时间戳常量。例如,Java 客户端中的此常量为Value.COMMIT_TIMESTAMP。
当 Spanner 使用这些占位符作为列值提交事务时,实际提交时间戳将写入指定的列。然后,您可以使用此列值来创建表的更新历史记录。
提交时间戳的值不保证是唯一的。写入不重叠字段集的事务可能具有相同的时间戳。写入重叠字段集的事务具有唯一的时间戳。
Spanner 提交时间戳具有微秒精度,当存储在 SPANNER.COMMIT_TIMESTAMP 列中时会转换为纳秒。
键和索引
您可以使用提交时间戳列作为主键列或非键列。主键可以定义为 ASC 或 DESC。
ASC(默认)- 升序键适用于解答从特定时间往前的查询。DESC- 降序键将最新的行保留在表的顶部,可提供对最近记录的快速访问。
避开热点
在以下情况下使用提交时间戳会引发热点,这会降低数据的性能:
提交时间戳列是表的主键的第一部分。
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;提交时间戳主键列是二级索引的第一部分。
CREATE INDEX UsersByLastAccess ON Users(LastAccess)或
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
出现热点后,即使写入速率较低,也会降低数据的性能。如果在没有索引的非键列上启用提交时间戳,则不会产生任何性能开销。
将提交时间戳列添加到现有表中
要将提交时间戳列添加到现有表中,请使用 ALTER TABLE 语句。例如,要将 LastUpdateTime 列添加到 Performances 表中,请使用以下语句:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
使用 DML 语句写入提交时间戳
使用 SPANNER.PENDING_COMMIT_TIMESTAMP() 函数在 DML 语句中写入提交时间戳。Spanner 会在事务提交时选择提交时间戳。
以下 DML 语句使用提交时间戳更新 Performances 表中的 LastUpdateTime 列:
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
使用变更插入行
插入行时,只有将列包含在列列表中并传递 spanner.commit_timestamp() 占位符字符串(或客户端库常量)作为其值时,Spanner 才会写入提交时间戳值。例如:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
如果在多个表的行中存在变更,则必须为每个表的提交时间戳列指定 spanner.commit_timestamp()(或客户端库常量)。
使用变更来更新行
更新行时,只有将列包含在列列表中并传递 spanner.commit_timestamp() 占位符字符串(或客户端库常量)作为其值时,Spanner 才会写入提交时间戳值。您无法更新某一行的主键。要更新主键,请删除现有行并创建一个新行。
例如,要更新名为 LastUpdateTime 的提交时间戳列,请执行以下操作:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
如果在多个表的行中存在变更,则必须为每个表的提交时间戳列指定 spanner.commit_timestamp()(或客户端库常量)。
查询提交时间戳列
以下示例展示了如何查询表的提交时间戳列。