本頁面說明如何在 GoogleSQL 方言資料庫和 PostgreSQL 方言資料庫中,對 Spanner 資料表使用存留時間 (TTL)。詳情請參閱「關於存留時間」。
事前準備
開始之前,請先遵循下列最佳做法。
啟用備份和時間點復原功能
建議您先啟用 Spanner 備份與還原,再將 TTL 新增至資料表。這樣一來,如果因存留時間政策而意外刪除資料,您就能完整還原資料庫。
如果已啟用時間點復原功能,只要在設定的版本保留期限內,即可查看及還原已刪除的資料,不必從備份完整還原。如要瞭解如何讀取過去的資料,請參閱執行過時讀取。
清理舊資料
如果您是第一次使用 TTL,且預期第一次執行會刪除許多資料列,請考慮先使用分區 DML 手動清除舊資料。 這樣您就能進一步控管資源用量,不必交由 TTL 背景程序處理。TTL 的執行優先順序較低,適合用於增量清除。不過,由於 Spanner 的內部工作排程器會優先處理其他工作 (例如使用者查詢),因此在繁忙的資料庫中,這可能會延長刪除初始列集的時間。
驗證條件
如果是 GoogleSQL 表格,您可以在啟用存留時間前,使用相同條件查詢表格,驗證資料是否會受到資料列刪除政策影響。例如:
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_days是指資料列標示為刪除後,經過的天數 (以timestamp_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_specvar> ON timestamp_column_name;
更改下列內容:
timestamp_column_name必須是資料類型為TIMESTAMPTZ的資料欄。您需要在CREATE TABLE陳述式中建立這個資料欄。含有修訂時間戳記的資料欄是有效的,產生的資料欄也是如此。不過,您無法指定參照修訂時間戳記欄的產生資料欄。interval_spec是指資料列標示為刪除的時間戳記 (timestamp_column_name) 經過的天數。這個值必須是非負整數,且必須評估為整數天數。舉例來說,'3 days'可以使用,但'3 days - 2 minutes'會傳回錯誤。
如要將政策新增至現有資料表,請使用 ALTER TABLE 陳述式。一個資料表最多只能有一項存留時間政策。如果資料表已有存留時間政策,新增政策時會發生錯誤。如要指定更精細的存留時間邏輯,請參閱「產生的資料欄的存留時間」。
如要將政策新增至現有資料表,請按照下列步驟操作:
ALTER TABLE albums
ADD COLUMN timestampcolumn TIMESTAMPTZ;
ALTER TABLE albums
ADD TTL INTERVAL '5 days' ON timestampcolumn;
限制
資料列刪除政策有下列限制。
外鍵參照的資料表存留時間
您無法建立資料列刪除政策:
在下列範例中,您無法將資料列刪除政策新增至 Customers 資料表,因為 Orders 資料表中的外鍵會參照該資料表,而 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 外鍵限制所參照。
含有預設值的資料欄的存留時間
資料列刪除政策可以使用預設值的時間戳記資料欄。一般預設值為 CURRENT_TIMESTAMP。如果沒有明確為資料欄指派值,或是資料欄透過 INSERT 或 UPDATE 陳述式設為預設值,系統會在規則計算中使用預設值。
在以下範例中,資料表 Customers 中資料欄 CreatedAt 的預設值是建立資料列時的時間戳記。
GoogleSQL
CREATE TABLE Customers (
CustomerID INT64,
CreatedAt TIMESTAMP DEFAULT (CURRENT_TIMESTAMP())
) PRIMARY KEY (CustomerID);
詳情請參閱「DEFAULT (運算式)」。
PostgreSQL
CREATE TABLE customers (
customerid bigint NOT NULL,
createdat timestamptz DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(customerid)
);
詳情請參閱「CREATE TABLE」。
生成資料欄的存留時間
資料列刪除政策可以使用產生的資料欄,表示更精細的規則。舉例來說,您可以針對多個資料欄的 greatest 時間戳記 (GoogleSQL 或 PostgreSQL) 定義資料列刪除政策,也可以將其他值對應至時間戳記。
GoogleSQL
下表 (名為 Orders) 會追蹤銷售訂單。表格擁有者想設定資料列刪除政策,在 30 天後刪除已取消的訂單,並在 180 天後刪除未取消的訂單。
Spanner 存留時間政策只能為每個資料表設定一項資料列刪除政策。如要在單一資料欄中表示這兩項條件,可以使用含有 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 存留時間政策只能為每個資料表設定一項資料列刪除政策。如要在單一資料欄中表示這兩項條件,可以建立產生的資料欄:
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 的產生資料欄,評估兩個日期 (LastModifiedDate 或 CreateDate) 中較近的日期。接著,這項陳述式會定義資料列刪除政策,在訂單建立 30 天後刪除資料列;如果訂單在這 30 天內經過修改,刪除時間會再延後 30 天。
存留時間和交錯式資料表
交錯式資料表是一種效能最佳化方式,可將一對多子項資料表中的相關資料列與父項資料表中的資料列建立關聯。如要在父項資料表上新增資料列刪除政策,所有交錯式子項資料表都必須指定 ON DELETE CASCADE,也就是說,子項資料列會與父項資料列一併刪除。這可確保參照完整性,因此在父項資料表上刪除資料列時,也會在同一交易中刪除相關的子項資料列。Spanner TTL 不支援 ON DELETE NO ACTION。
交易大小上限
Spanner 設有交易大小限制。 如果大型父項/子項階層含有已建立索引的資料欄,連鎖刪除作業可能會超出這些限制,導致一或多項存留時間作業失敗。如果作業失敗,TTL 會以較小的批次重試,直到單一父項資料列為止。不過,即使是單一父項資料列的大型子項階層,仍可能超出變動限制。
失敗的作業會回報在 TTL 指標中。
如果單一資料列及其交錯子項過大而無法刪除,除了父項資料表上的資料列刪除政策外,您也可以直接在子項資料表上附加資料列刪除政策。子項資料表的政策應設定為先刪除子項資料列,再刪除父項資料列。
如果符合下列兩項陳述,請考慮將資料列刪除政策附加至子項資料表:
- 子資料表有任何相關聯的全域索引;以及
- 您預期每個父項資料列會有大量 (>100) 子項資料列。
刪除資料列刪除政策
您可以從資料表捨棄現有的資料列刪除政策。如果資料表沒有現有的資料列刪除政策,這項作業會傳回錯誤。
GoogleSQL
ALTER TABLE MyTable
DROP ROW DELETION POLICY;
PostgreSQL
ALTER TABLE mytable
DROP 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;