使用 TTL 管理数据保留

本页面介绍了如何在 Spanner 表上使用存留时间 (TTL)。接收者 如需了解详情,请参阅 TTL 简介

准备工作

开始之前,请遵循以下最佳实践。

启用备份和时间点恢复

在将 TTL 添加到您的表之前,我们建议您先启用 Spanner 备份和恢复。这样, 您可以完全恢复数据库,以防您不小心删除 TTL 政策。

如果您已启用时间点恢复,并且已删除的数据在已配置的版本保留期限内,则可以查看和恢复这些数据,而不必从备份进行完全恢复。如需了解如何读取过去的数据,请参阅执行过时读取

清理旧数据

如果这是您第一次使用 TTL,并且您希望首次运行 删除多行,请考虑先使用以下代码手动清理旧数据 分区 DML。 这样,您就可以更好地控制资源使用情况,而不必将其留给 TTL 后台进程。TTL 以低优先级运行,非常适合用于增量更改 清理。但是,这可能会延长删除 由于 Spanner 的内部原因, 工作调度程序会优先处理其他工作,例如用户查询。

验证您的条件

对于 GoogleSQL 表,如果您希望在启用 TTL 之前验证行删除政策将会影响的数据,则可以使用相同的条件查询表。例如:

GoogleSQL

  SELECT COUNT(*)
  FROM CalculatedRoutes
  WHERE TIMESTAMP_ADD(CreatedAt, INTERVAL 30 DAY) < CURRENT_TIMESTAMP();

所需权限

如需更改数据库的架构,您必须具有 spanner.databases.updateDdl 权限。有关详情,请参阅 Spanner 的访问权限控制

创建行删除政策

GoogleSQL

如需使用 GoogleSQL 创建行删除政策,您可以在创建新表时定义 ROW DELETION POLICY 子句,也可以向现有表添加政策。此子句包含一个列的表达式和一个 。

如需在创建表时添加政策,请执行以下操作:

CREATE TABLE MyTable(
Key INT64,
CreatedAt TIMESTAMP,
) PRIMARY KEY (Key),
ROW DELETION POLICY (OLDER_THAN(timestamp_column, INTERVAL num_days DAY));

其中:

  • timestamp_column”必须是现有列 类型为 TIMESTAMP。包含以下内容的列 提交时间戳有效,同样 生成的列。但是,您不能 指定引用了提交时间戳列的生成列。

  • num_daystimestamp_column(其中相应行被标记了)中的时间戳 删除。该值必须是非负整数,DAY 是唯一的 支持的单位。

如需向现有表添加政策,请使用 ALTER TABLE 语句。每个表最多只能有一个行删除政策。添加行删除政策 附加到具有现有政策的表将失败并显示错误。请参阅生成的列上的 TTL 以指定更复杂的行删除逻辑。

ALTER TABLE Albums
ADD ROW DELETION POLICY (OLDER_THAN(timestamp_column, INTERVAL num_days DAY));

PostgreSQL

如需使用 PostgreSQL 创建行删除政策,您可以在创建新表时定义 TTL INTERVAL 子句,也可以向现有表添加政策。

如需在创建表时添加政策,请执行以下操作:

CREATE TABLE mytable (
  key bigint NOT NULL,
  timestamp_column_name TIMESTAMPTZ,
  PRIMARY KEY(key)
) TTL INTERVAL interval_spec ON timestamp_column_name;

其中:

  • timestamp_column_name”必须是包含 数据类型为 TIMESTAMPTZ。您需要在 CREATE TABLE 语句中创建此列。包含以下内容的列 提交时间戳有效,同样 生成的列。但是,您不能 指定引用了提交时间戳列的生成列。

  • interval_spectimestamp_column_name 中将行标记为待删除的时间戳之后的天数。该值必须是非负整数,并且必须为整数天数。例如,允许使用 '3 days',但 '3 days - 2 minutes' 会返回错误。

如需向现有表添加政策,请使用 ALTER TABLE 语句。答 表最多只能有一项 TTL 政策。将 TTL 政策添加到采用如下设置的表 现有政策因错误而失败。请参阅 对生成的列采用 TTL 来指定更多 复杂的 TTL 逻辑。

如需向现有表添加政策,请执行以下操作:

ALTER TABLE albums
ADD COLUMN timestampcolumn TIMESTAMPTZ;

ALTER TABLE albums
ADD TTL INTERVAL '5 days' ON timestampcolumn;

限制

行删除政策具有以下限制。

对外键引用的表使用 TTL

您无法在以下对象上创建行删除政策:

  • 在由 不包含 ON 的外键 DELETE CASCADE 约束条件。
  • 在由非外部键引用的表的父级上 包含 ON DELETE CASCADE 参照操作。

在以下示例中,您不能向 Customers 表,因为它由 Orders 中的外键引用 表,该表没有 ON DELETE CASCADE 约束条件。 删除客户可能会违反此外键限制条件。此外,你也不能 向 Districts 表添加行删除政策。从以下位置删除行: Districts 可能会导致删除操作在子 Customers 表中级联,这 可能违反 Orders 表的外键约束条件。

GoogleSQL

CREATE TABLE Districts (
  DistrictID INT64
) PRIMARY KEY (DistrictID);

CREATE TABLE Customers (
  DistrictID INT64,
  CustomerID INT64,
  CreatedAt TIMESTAMP
) PRIMARY KEY (DistrictID, CustomerID),
INTERLEAVE IN PARENT Districts ON DELETE CASCADE;

CREATE TABLE Orders (
  OrderID INT64,
  DistrictID INT64,
  CustomerID INT64,
  CONSTRAINT FK_CustomerOrder FOREIGN KEY (DistrictID, CustomerID) REFERENCES Customers (DistrictID, CustomerID)
) PRIMARY KEY (OrderID);

PostgreSQL

CREATE TABLE districts (
  districtid   bigint NOT NULL,
  PRIMARY KEY(districtid)
);

CREATE TABLE customers (
  districtid   bigint NOT NULL,
  customerid   bigint NOT NULL,
  createdat  timestamptz,
  PRIMARY KEY(districtid, customerid)
) INTERLEAVE IN PARENT districts ON DELETE CASCADE;

CREATE TABLE orders (
  orderid bigint NOT NULL,
  districtid   bigint,
  customerid bigint,
  PRIMARY KEY(orderid),
  CONSTRAINT fk_customerorder FOREIGN KEY (districtid, customerid) REFERENCES customers (districtid, customerid)
);

您可以在由使用 ON DELETE CASCADE 的外键约束条件引用的表上创建行删除政策。在以下示例中,您可以 在 Customers 表上创建行删除政策 在 Orders 表中定义的外键约束条件 CustomerOrder。时间 TTL 会删除 Customers 中的行,删除操作会级联到匹配的行 位于“Orders”表中

GoogleSQL

 CREATE TABLE Districts (
  DistrictID INT64,
  CreatedAt TIMESTAMP
) PRIMARY KEY (DistrictID),
ROW DELETION POLICY (OLDER_THAN(CreatedAt, INTERVAL 1 DAY));

CREATE TABLE Customers (
  DistrictID INT64,
  CustomerID INT64,
  CreatedAt TIMESTAMP
) PRIMARY KEY (DistrictID, CustomerID),
INTERLEAVE IN PARENT Districts ON DELETE CASCADE,
ROW DELETION POLICY (OLDER_THAN(CreatedAt, INTERVAL 1 DAY));

CREATE TABLE Orders (
  OrderID INT64,
  DistrictID INT64,
  CustomerID INT64,
  CONSTRAINT FK_CustomerOrder FOREIGN KEY (DistrictID, CustomerID) REFERENCES Customers (DistrictID, CustomerID) ON DELETE CASCADE
) PRIMARY KEY (OrderID);

PostgreSQL

CREATE TABLE districts (
  districtid   bigint NOT NULL,
  createdat  timestamptz,
  PRIMARY KEY(districtid)
) TTL INTERVAL '1 day' ON createdat;

CREATE TABLE customers (
  districtid   bigint NOT NULL,
  customerid   bigint NOT NULL,
  createdat  timestamptz,
  PRIMARY KEY(districtid, customerid)
) INTERLEAVE IN PARENT districts ON DELETE CASCADE
TTL INTERVAL '1 day' ON createdat;

CREATE TABLE orders (
  orderid bigint NOT NULL,
  districtid bigint,
  customerid bigint,
  PRIMARY KEY(orderid),
  CONSTRAINT fk_customerorder FOREIGN KEY (districtid, customerid) REFERENCES customers (districtid, customerid) ON DELETE CASCADE
);

同样,您可以在一个表的父表上创建行删除政策, 由 ON DELETE CASCADE 外键约束条件引用。

采用默认值的列的 TTL

行删除政策可以使用具有默认值的时间戳列。典型 默认值为 CURRENT_TIMESTAMP。如果没有明确向 或者通过 INSERT 将此列设置为默认值,或者 UPDATE 语句,则在规则计算中使用默认值。

在以下示例中,表中 CreatedAt 列的默认值 Customers 是创建该行的时间戳。

GoogleSQL

CREATE TABLE Customers (
  CustomerID INT64,
  CreatedAt TIMESTAMP DEFAULT (CURRENT_TIMESTAMP())
) PRIMARY KEY (CustomerID);

如需了解详情,请参阅“GoogleSQL 数据定义语言”中的 DEFAULT (expression)

PostgreSQL

CREATE TABLE customers (
  customerid bigint NOT NULL,
  createdat timestamptz DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY(customerid)
  );

如需了解详情,请参阅创建表

生成的列上的 TTL

行删除政策可以使用生成的列 来表达更复杂的规则例如,您可以定义删除行 针对多列的 greatest 时间戳(GoogleSQLPostgreSQL)应用的政策,或者将另一个值映射到 时间戳。

GoogleSQL

下表(名为 Orders)用于跟踪销售订单。 表所有者想要设置一个行删除政策,以便在 30 天后删除已取消的订单,并在 180 天后删除未取消的订单。

Spanner TTL 仅允许每个表有一项行删除政策。接收者 在单个列中表示两个条件,您可以使用生成的列 使用 IF 语句:

CREATE TABLE Orders (
  OrderId INT64 NOT NULL,
  OrderStatus STRING(30) NOT NULL,
  LastModifiedDate TIMESTAMP NOT NULL,
  ExpiredDate TIMESTAMP AS (IF(OrderStatus = 'Cancelled',
    TIMESTAMP_ADD(LastModifiedDate, INTERVAL 30 DAY),
    TIMESTAMP_ADD(LastModifiedDate, INTERVAL 180 DAY))) STORED,
) PRIMARY KEY(OrderId),
ROW DELETION POLICY (OLDER_THAN(ExpiredDate, INTERVAL 0 DAY));

该语句会创建一个名为 ExpiredDate 的列,该列会根据订单状态向 LastModifiedDate 添加 30 天或 180 天。然后通过指定 INTERVAL 0 day,将行删除政策指定为让行在 ExpiredDate 列中存储的日期过期。

PostgreSQL

下表(名为 Orders)用于跟踪销售订单。 表所有者想要设置用于删除行的行删除政策 处于非活跃状态 30 天后。

Spanner TTL 仅允许每个表有一项行删除政策。接收者 在单个列中表示两个条件,则可以创建一个生成的 列:

CREATE TABLE orders (
    orderid bigint NOT NULL,
    orderstatus varchar(30) NOT NULL,
    createdate timestamptz NOT NULL,
    lastmodifieddate timestamptz,
    expireddate timestamptz GENERATED ALWAYS AS (GREATEST(createdate, lastmodifieddate)) STORED,
    PRIMARY KEY(orderid)
) TTL INTERVAL '30 days' ON expireddate;

该语句会创建一个名为 ExpiredDate 的生成列,用于评估 两个日期(LastModifiedDateCreateDate)中最近的那个日期。 然后,定义行删除政策,使行在 订单,或者订单在这 30 天内发生了修改 则会将删除期限再延长 30 天。

TTL 和交错表

交错表是将一对多子表中的相关行与父表中的行相关联的性能优化。如需在父表上添加行删除政策,所有交错子表都必须指定 ON DELETE CASCADE,这意味着子行将与父行一起以原子方式删除。这样可以确保参照完整性,以便父表上的删除也会删除同一事务中的相关子行。Spanner TTL 的用途 不支持 ON DELETE NO ACTION

事务大小上限

Spanner 设有事务大小限制。 在具有索引列的大型父子层次结构上执行级联删除 超出这些限制,并导致一项或多项 TTL 操作失败。对于失败的操作,TTL 将使用较小的批量进行重试,最小的批量为单个父行。但是,即使是单个父行的大型子层次结构仍有可能超出变更限制。

TTL 指标中将会报告失败的操作。

如果单行及其交错的子项因太大而无法删除,可以 除了 一个父表。子表上的政策应配置为 先删除父行,再删除子行。

当以下两个语句适用时,请考虑将行删除政策附加到子表:

  • 子表具有任何与之关联的全局索引;且
  • 每个父行预计包含大量 (>100) 子行。

删除行删除政策

您可以从表中删除现有行删除政策。如果表上没有行删除政策,则返回错误。

GoogleSQL

ALTER TABLE MyTable
DROP ROW DELETION POLICY;

PostgreSQL

ALTER TABLE mytable
DROP TTL;

删除行删除政策会立即中止在后台运行的任何 TTL 进程。正在进行的进程已删除的所有行都将被删除。

删除行删除政策引用的列

Spanner 不允许您删除被引用的列 行删除政策您必须先删除行删除政策,然后才能删除该列。

查看表的行删除政策

您可以查看 Spanner 表的行删除政策。

GoogleSQL

SELECT TABLE_NAME, ROW_DELETION_POLICY_EXPRESSION
FROM INFORMATION_SCHEMA.TABLES
WHERE ROW_DELETION_POLICY_EXPRESSION IS NOT NULL;

如需了解详情,请参阅 GoogleSQL 方言数据库的信息架构

PostgreSQL

SELECT table_name, row_deletion_policy_expression
FROM information_schema.tables
WHERE row_deletion_policy_expression is not null;

如需了解详情,请参阅 PostgreSQL 方言数据库的信息架构

修改行删除政策

您可以更改现有行删除政策的列或间隔表达式。以下示例将列从 CreatedAt 切换为 ModifiedAt,并将间隔从 1 DAY 延长到 7 DAY。这将返回一个 错误。

GoogleSQL

ALTER TABLE MyTable
REPLACE ROW DELETION POLICY (OLDER_THAN(ModifiedAt, INTERVAL 7 DAY));

PostgreSQL

ALTER TABLE mytable
ALTER TTL INTERVAL '7 days' ON timestampcolumn;