跳到主要内容
版本:v3.0.x

设置 Collection TTL

Milvus 可通过 "**存活时间"(TTL)**策略自动使实体过期。过期的实体会立即停止出现在查询和搜索结果中,并在下一个压缩周期(通常是 24 小时内)从存储中物理移除。

有两种 TTL 模式:

  • Collection 级 TTL- 每个实体共享一个保留窗口,通过collection.ttl.seconds 属性设置。

  • 实体级 TTL- 每个实体在专用的TIMESTAMPTZ 字段中都有自己的绝对过期时间,通过ttl_field 属性标记为 TTL 字段。

说明

此功能仅适用于管理的 Collection。

限制

  • 两种 TTL 模式是相互排斥的。一个 Collection 不能同时设置collection.ttl.secondsttl_field 。要进行切换,请参阅在两种模式之间迁移

  • Collection 级 TTL 对整个 Collection 应用一个窗口。如果单行需要不同的生命周期,请使用实体级 TTL。

  • 实体级 TTL 的字段必须是TIMESTAMPTZ 。其他类型将被拒绝。

  • 每个 Collection 只有一个 TTL 字段。Schema 可以包含多个TIMESTAMPTZ 字段,但只有一个可以用ttl_field 命名。

  • 删除ttl_field 不会恢复已过期的实体。要恢复过期实体,请使用NULL 或未来过期时间戳重新插入。

概述

展开

何时使用 TTL

当保留是一项策略时,TTL 是最合适的工具--你预先知道某些实体最终会消失,而且你希望群集在你不编写 cron 作业的情况下强制执行它。

典型应用场景

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

  • **多租户 Collection。**不同租户在同一 Collection 中拥有不同的保留窗口。

  • **按记录保留策略。**物联网管道、文档存储或 MLOps 特征存储中的每个文档生命周期。

  • **热/冷数据混合。**在同一 Collection 中,短期实体与长期实体共存。

  • **合规驱动的过期。**GDPR 式的数据最小化,每条记录都有自己的 "删除日期"。

  • **业务时间过期。**实体代表的记录只在某个绝对时刻(活动结束、会话过期)前有效。

说明

过期实体不会出现在任何搜索或查询结果中。不过,它们可以保留在存储中,直到随后的数据压缩(应在接下来的 24 小时内进行)。

你可以通过设置 Milvus 配置文件中的dataCoord.compaction.expiry.tolerance 配置项来控制何时触发数据压缩。

该配置项的默认值为-1 ,表示适用现有的数据压实间隔。但是,如果将其值改为正整数,如12 ,则会在任何实体过期后的指定小时数触发数据压缩。

TTL 模式

这两种模式回答了不同的保留问题:

  • Collection 级 TTL对每个实体应用单一的保留期限。每个实体在insert_ts + ttl_seconds 时过期。

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

Collection 一次使用一种模式--这两种模式是相互排斥的。在两种模式之间切换需要多步操作;请参阅在两种模式之间迁移。

使用此表选择一种模式:

| 如果您的情况是...

|

使用

| | --- | --- | |

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

|

Collection 级 TTL

| |

保留时间为 "从插入开始,保留 N 秒"。

|

Collection 级 TTL

| |

在同一个 Collection 中,不同的实体需要不同的生命周期(按租户、热/冷、按文档)。

|

实体级 TTL

| |

保留时间是绝对的挂钟时间(例如,2027-01-01T00:00:00Z)

|

实体级 TTL

| |

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

|

实体级 TTL

| |

您想在插入后刷新或延长实体的生命周期

|

实体级 TTL

| |

有些实体永远不会过期,而其他实体则应该过期

|

实体级 TTL(不朽的实体使用 NULL)

|

设置 Collection 级 TTL

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

在新 Collection 上启用

在创建时通过properties 映射传递collection.ttl.seconds (整数,以秒为单位)。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost: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,
properties={
"collection.ttl.seconds": 1209600 # 14 days
},
)

在现有 Collection 上启用

通过properties 映射中的collection.ttl.seconds 调用alter_collection_properties ,将 TTL 应用于已在使用的 Collection。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost: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,
)

client.alter_collection_properties(
collection_name="my_collection",
properties={"collection.ttl.seconds": 1209600},
)

放弃 TTL 设置

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

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

client.drop_collection_properties(
collection_name="my_collection",
property_keys=["collection.ttl.seconds"],
)

设置实体级 TTLCompatible with Milvus 3.0.x

实体级 TTL 允许每个实体拥有自己的绝对过期时间。时间存储在您在 Schema 中声明的专用TIMESTAMPTZ 列中,您可以通过ttl_field Collection 属性将该列标记为 TTL 字段。

在新的 Collection 上启用

在创建时启用实体级 TTL 需要在同一个create_collection 调用中添加两个内容:Schema 中的TIMESTAMPTZ 字段和指向该字段的ttl_field 属性。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

schema = client.create_schema(enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
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,
properties={"ttl_field": "expire_at"},
)

Collection 存在后,插入带有ISO 8601时间戳字符串的实体。

import random
from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

# Assumes "my_collection" was created earlier with `ttl_field`: "expire_at"
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)

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

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

client.load_collection("my_collection")

# 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)

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

要想在物理压实删除实体之前延长其生命周期,可以使用较晚的过期时间戳(或None )upsert,将实体返回到可查询集。

import random
from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

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

在现有 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="http://localhost:19530")

# 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"},
])

取消 TTL 设置

property_keys 中使用ttl_field 调用drop_collection_properties ,以停止按实体过期。TIMESTAMPTZ 列本身仍保留在 Schema 上 - 您仍可将其作为常规字段进行查询。

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

client.drop_collection_properties(
collection_name="my_collection",
property_keys=["ttl_field"],
)

删除ttl_field 会禁用未来查询的自动过滤功能,但已过期的实体不会再次自动浮现。要使以前过期的实体可见,请使用None 或未来过期时间戳重新插入,这是在同一加载会话中恢复访问过期行的唯一方法。

在两种模式之间迁移

两种 TTL 模式是互斥的,因此在它们之间切换需要多步操作符。

从 Collection 级 TTL 切换到实体级 TTL

如果你的 Collection 是用collection.ttl.seconds 创建的,而你想切换到按实体过期,请按照以下四个步骤操作。跳过步骤 1 会导致步骤 3 失败,collection TTL is already set, cannot be set ttl field

import random
from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

# Assumes "my_collection" already exists with `collection.ttl.seconds` set.
# 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"},
])

不回填expire_at 的历史实体在该列中将有NULL ,这意味着它们永远不会过期。只回填应具有有限生命周期的行。

从实体级 TTL 切换到 Collection 级 TTL

要向另一个方向移动,请放弃ttl_field 并设置collection.ttl.seconds

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

# Assumes "my_collection" already exists with `ttl_field` set.
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
)

常见问题

TTL 设置导致数据何时过期?

目前,数据的过期时间基于插入或上插的时间点。过期数据不会显示在搜索结果中。有关详细信息,请参阅示例

过期数据何时会被物理删除?

数据过期后,将不会出现在任何搜索结果中。不过,只有在随后的系统压缩后,才会根据群集的压缩策略对其进行物理删除。