跳到主要内容
版本:Cloud 开发指南

设置 Collection 生存时间

Zilliz Cloud 可以通过 Time-to-Live (TTL) 策略自动让 Entity 过期。过期的 Entity 会立刻停止出现在查询和搜索结果中,并会在下一次 Compaction 周期从存储中被物理删除——通常在 24 小时内完成。

TTL 有两种模式:

  • Collection 级 TTL——整个 Collection 中的所有 Entity 共用一个保留窗口,通过 collection.ttl.seconds 属性设置。

  • Entity 级 TTL——每个 Entity 在专用的 TIMESTAMPTZ 字段中携带自己的绝对过期时间,并通过 ttl_field 属性将该字段标记为 TTL 字段。

限制

  • 两种 TTL 模式互斥。一个 Collection 不能同时设置 collection.ttl.secondsttl_field。如需切换,请参见在两种模式之间迁移

  • Collection 级 TTL 为整个 Collection 应用同一个保留窗口。如果某一行需要不同的生命周期,请使用 Entity 级 TTL。

  • 用于 Entity 级 TTL 的字段必须是 TIMESTAMPTZ 类型。其他类型会被拒绝。

  • 每个 Collection 只能有一个 TTL 字段。Schema 中可以包含多个 TIMESTAMPTZ 字段,但只能将其中一个指定为 ttl_field

  • 删除 ttl_field 不会让已过期的 Entity 重新出现。要恢复一个已过期的 Entity,需要使用 NULL 或未来的过期时间戳对其执行 Upsert。

概述

展开

何时使用 TTL

当数据保留是一项策略时,TTL 是合适的工具——也就是说,您预先知道某些 Entity 最终应该被移除,并希望由集群自动执行这一策略,而不是由您编写定时任务。

典型场景包括:

  • 时间窗口数据集。 仅保留最近 N 天的日志、指标、事件或短期特征缓存。

  • 多租户 Collection。 同一个 Collection 中不同租户具有不同的保留窗口。

  • 逐条数据保留策略。 IoT 流水线、文档存储或 MLOps 特征存储中的单文档生命周期。

  • 冷热数据混合。 短期 Entity 与长期 Entity 共存于同一个 Collection 中。

  • 合规驱动的过期。 类似 GDPR 的数据最小化场景,每条数据都携带自己的"删除截止时间"。

  • 业务时间过期。 Entity 表示只在某个绝对时间点之前有效的数据,例如活动结束或会话过期。

📘说明

过期数据不会出现在搜索和查询结果中,并会在下一次数据压缩时删除。数据压缩间隔通常不会超过 24 小时。

TTL 模式

两种模式回答的是不同的数据保留问题:

  • Collection 级 TTL 对每个 Entity 应用同一个保留时长。每个 Entity 会在 insert_ts + ttl_seconds 时过期。

  • Entity 级 TTL 允许每个 Entity 在 TIMESTAMPTZ 字段中存储自己的绝对过期时间。该字段中的 NULL 表示该 Entity 永不过期。

一个 Collection 一次只能使用一种模式——两种模式互斥。在两种模式之间切换是一个多步骤操作;请参见在两种模式之间迁移

您可以使用下表选择模式:

如果您的场景是……

使用

Collection 中的每个 Entity 都应遵循相同的保留窗口

Collection 级 TTL

保留策略是"从插入时刻开始保留 N 秒"

Collection 级 TTL

同一个 Collection 中不同 Entity 需要不同生命周期(按租户、冷热数据或逐文档控制)

Entity 级 TTL

保留策略是绝对墙钟时间(例如 2027-01-01T00:00:00Z)

Entity 级 TTL

保留策略由业务时间戳驱动,而不是由插入时间戳驱动

Entity 级 TTL

您希望在插入后刷新或延长 Entity 的生命周期

Entity 级 TTL

部分 Entity 应永不过期,而其他 Entity 应过期

Entity 级 TTL(对永不过期的 Entity 使用 NULL)

设置 Collection 级TTL

当 Collection 中的每个 Entity 都应遵循相同的保留窗口时,使用 Collection 级 TTL。

在新 Collection 上启用

在创建 Collection 时,通过 properties map 传入 collection.ttl.seconds(整数,单位为秒)。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)

index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector", index_type="AUTOINDEX", metric_type="COSINE"
)

client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params,
# highlight-start
properties={
"collection.ttl.seconds": 1209600 # 14 days
},
# highlight-end
)

在已有 Collection 上启用

调用 alter_collection_properties 并在 properties map 中传入 collection.ttl.seconds,即可为已在使用中的 Collection 启用 TTL。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# Assumes "my_collection" was created earlier without TTL
schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)

index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector", index_type="AUTOINDEX", metric_type="COSINE"
)

if not client.has_collection("my_collection"):
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params,
)

# highlight-start
client.alter_collection_properties(
collection_name="my_collection",
properties={"collection.ttl.seconds": 1209600},
)
# highlight-end

删除 TTL 设置

如果您决定无限期保留某个 Collection 中的数据,只需删除该 Collection 上的 TTL 设置即可。

from pymilvus import MilvusClient

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# highlight-start
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["collection.ttl.seconds"],
)
# highlight-end

设置 Entity 级 TTL

Entity 级 TTL 允许每个 Entity 携带自己的绝对过期时间。过期时间存储在您在 Schema 中声明的专用 TIMESTAMPTZ 字段中,并通过 ttl_field Collection 属性将该字段标记为 TTL 字段。

在新 Collection 上启用
内测版

在创建时启用 Entity 级 TTL,需要在同一个 create_collection 调用中完成两处新增:在 Schema 中加入一个 TIMESTAMPTZ 字段,并通过 ttl_field 属性指向该字段。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

schema = client.create_schema(enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
# highlight-next-line
schema.add_field("expire_at", DataType.TIMESTAMPTZ, nullable=True)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)

index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="AUTOINDEX",
metric_type="COSINE")

client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params,
# highlight-next-line
properties={"ttl_field": "expire_at"},
)

Collection 创建完成后,写入 Entity 时使用 ISO 8601 格式的时间戳字符串。

import random
from pymilvus import MilvusClient

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# Assumes "my_collection" was created earlier with \`ttl_field\`: "expire_at"
# highlight-start
rows = [
# Never expires
{"id": 1, "expire_at": None,
"vector": [random.random() for _ in range(128)]},
# Expires at 2026-12-31 UTC midnight
{"id": 2, "expire_at": "2026-12-31T00:00:00Z",
"vector": [random.random() for _ in range(128)]},
# Shanghai local time — normalized to UTC internally
{"id": 3, "expire_at": "2027-01-01T00:00:00+08:00",
"vector": [random.random() for _ in range(128)]},
]

client.insert("my_collection", rows)
# highlight-end

在每次查询和向量搜索时,服务器都会自动注入 TTL 过滤条件——您无需自己编写,过期 Entity 也永远不会出现在结果中:

from pymilvus import MilvusClient

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

client.load_collection("my_collection")

# highlight-start
# Expired rows are filtered out automatically
results = client.query(
collection_name="my_collection",
filter="id >= 0",
output_fields=["id", "expire_at"],
limit=10,
)
print(results)
# highlight-end

同样的自动过滤也适用于 client.search()

要在 Compaction 物理删除某个 Entity 之前延长其生命周期,可以使用更晚的过期时间戳(或 None)执行 Upsert,使该 Entity 重新回到可查询 Collection 中。

import random
from pymilvus import MilvusClient

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# highlight-start
client.upsert("my_collection", [
{"id": 2,
"vector": [random.random() for _ in range(128)],
"expire_at": "2028-01-01T00:00:00Z"},
])
# highlight-end

在已有 Collection 上启用

如果 Collection 已存在且未设置 collection.ttl.seconds,可使用 add_collection_field 新增一个 TIMESTAMPTZ 字段,然后通过 alter_collection_properties 将其标记为 TTL 字段。可选地,对历史数据执行 Upsert 来回填过期时间戳——未回填的行保持为 NULL,将永不过期。

import random
from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# highlight-start
# Step 1 — add a TIMESTAMPTZ column to the schema
client.add_collection_field(
collection_name="my_collection",
field_name="expire_at",
data_type=DataType.TIMESTAMPTZ,
nullable=True,
)

# Step 2 — mark the new column as the TTL field
client.alter_collection_properties(
collection_name="my_collection",
properties={"ttl_field": "expire_at"},
)

# Step 3 (optional) — backfill expiration timestamps for historical rows
client.upsert("my_collection", [
{"id": 1,
"vector": [random.random() for _ in range(128)],
"expire_at": "2026-12-31T00:00:00Z"},
])
# highlight-end

删除 TTL 设置

调用 drop_collection_properties 并在 property_keys 中传入 ttl_field,即可停用逐条 Entity 过期。TIMESTAMPTZ 字段本身仍保留在 Schema 中——您仍然可以将其作为普通字段进行查询。

from pymilvus import MilvusClient

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# highlight-start
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["ttl_field"],
)
# highlight-end

删除 ttl_field 会使后续查询不再自动应用 TTL 过滤,但已经过期的 Entity 不会自动重新出现。要让一个已过期的 Entity 重新可见,需要使用 None 或未来的过期时间戳对其执行 Upsert——这是在同一次 load 会话中恢复对已过期数据访问的唯一方式。

在两种模式之间迁移
内测版

从 Collection 级切换到 Entity 级 TTL

如果您的 Collection 是使用 collection.ttl.seconds 创建的,希望切换为逐条 Entity 过期,请按以下四步执行。跳过 Step 1 会导致 Step 3 报错 collection TTL is already set, cannot be set ttl field

import random
from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# Assumes "my_collection" already exists with \`collection.ttl.seconds\` set.
# highlight-start
# Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["collection.ttl.seconds"],
)

# Step 2 — add a TIMESTAMPTZ column to the schema
client.add_collection_field(
collection_name="my_collection",
field_name="expire_at",
data_type=DataType.TIMESTAMPTZ,
nullable=True,
)

# Step 3 — set the ttl_field property on the column you just added
client.alter_collection_properties(
collection_name="my_collection",
properties={"ttl_field": "expire_at"},
)

# Step 4 (optional) — backfill expiration timestamps for historical entities
client.upsert("my_collection", [
{"id": 1,
"vector": [random.random() for _ in range(128)],
"expire_at": "2026-12-31T00:00:00Z"},
])
# highlight-end

未回填 expire_at 的历史 Entity 在该字段中保持 NULL,即永不过期。只为应当具备有限生命周期的行回填即可。

从 Entity 级切换到 Collection 级 TTL

要反向迁移,删除 ttl_field 并设置 collection.ttl.seconds

from pymilvus import MilvusClient

client = MilvusClient(uri="https://{cluster-id}.{region}.vectordb.zilliz.com.cn:19530")

# Assumes "my_collection" already exists with \`ttl_field\` set.
# highlight-start
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["ttl_field"],
)
client.alter_collection_properties(
collection_name="my_collection",
properties={"collection.ttl.seconds": 1209600}, # 14 days
)
# highlight-end

常见问题

插入 Collection 中的数据到底何时会根据 TTL 设置失效?

Zilliz Cloud 会根据TTL 设置及数据的插入或更新时间来确定其失效时间。失效的数据将不会出现在任何搜索结果中。具体可参考相关示例

失效数据何时会删除?{#}

当数据失效后,这些数据将不会出现在任何搜索结果中,但是,只有在 Zilliz Cloud 根据集群的数据压缩策略执行下一次压缩时,这些数据才会被删除。

如果您希望在数据失效后的较短时间内删除这些数据,请联系 Zilliz Cloud 技术支持

Zilliz Cloud 集群的 CU 容量何时会开始降低?

集群的 CU 容量会取内存使用量和存储使用量中的最大值。如果 CU 容量当前取的是存储使用量,您可以在失效数据被删除后,在 Zilliz Cloud 控制台中观察到 CU 容量的减少。