TIMESTAMPTZ 필드 (TIMESTAMPTZ Field)
Milvus 2.6.6+와 호환돼요.
전자상거래 시스템, 협업 도구, 분산 로깅처럼 지역을 넘나들며 시간을 추적하는 애플리케이션은 시간대가 포함된 타임스탬프를 정밀하게 처리해야 해요. Milvus의 TIMESTAMPTZ 데이터 타입은 타임스탬프와 관련 시간대를 함께 저장해 이 기능을 제공해요.
출처: Milvus 문서
본문
TIMESTAMPTZ 필드란? (What is a TIMESTAMPTZ field?)
TIMESTAMPTZ 필드는 Milvus의 스키마 정의 데이터 타입(DataType.TIMESTAMPTZ)으로, 시간대 인식 입력을 처리하고 모든 시점을 내부적으로 UTC 절대 시간으로 저장해요.
- 허용되는 입력 형식: 시간대 오프셋이 있는 ISO 8601 문자열(예:
"2025-05-01T23:59:59+08:00"은 2025년 5월 1일 오후 11시 59분 59초(UTC+08:00)를 나타냄). - 내부 저장: 모든
TIMESTAMPTZ값은 정규화되어 Coordinated Universal Time(UTC)으로 저장돼요. - 비교와 필터링: 모든 필터링과 정렬 연산은 UTC로 수행되어 서로 다른 시간대에서도 일관되고 예측 가능한 결과를 보장해요.
TIMESTAMPTZ필드에nullable=True를 설정해 누락 값을 허용할 수 있어요.- ISO 8601 형식의
default_value속성을 사용해 기본 타임스탬프 값을 지정할 수 있어요.
자세한 내용은 Nullable & Default를 참고하세요.
기본 연산 (Basic operations)
TIMESTAMPTZ 필드를 사용하는 기본 워크플로우는 Milvus의 다른 스칼라 필드와 같아요. 필드 정의 → 데이터 삽입 → 쿼리/필터링.
1단계: TIMESTAMPTZ 필드 정의 (Step 1)
TIMESTAMPTZ 필드를 사용하려면 컬렉션을 만들 때 컬렉션 스키마에 명시적으로 정의해야 해요. 다음 예시는 DataType.TIMESTAMPTZ 타입의 tsz 필드가 있는 컬렉션을 만드는 방법을 보여 줘요.
import time
from pymilvus import MilvusClient, DataType
import datetime
import pytz
server_address = "http://localhost:19530"
collection_name = "timestamptz_test123"
client = MilvusClient(uri=server_address)
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = client.create_schema()
# Add a primary key field
schema.add_field("id", DataType.INT64, is_primary=True)
# Add a TIMESTAMPTZ field that allows null values
schema.add_field("tsz", DataType.TIMESTAMPTZ, nullable=True)
# Add a vector field
schema.add_field("vec", DataType.FLOAT_VECTOR, dim=4)
client.create_collection(collection_name, schema=schema, consistency_level="Session")
print(f"Collection '{collection_name}' with a TimestampTz field created successfully.")
2단계: 데이터 삽입 (Step 2)
시간대 오프셋이 있는 ISO 8601 문자열을 포함하는 엔티티를 삽입해요.
아래 예시는 8,193행의 샘플 데이터를 컬렉션에 삽입해요. 각 행은 다음을 포함해요.
- 고유 ID.
- 시간대 인식 타임스탬프(상하이 시간).
- 간단한 4차원 벡터.
data_size = 8193
# Get the Asia/Shanghai time zone using the pytz library
# You can use any valid IANA time zone identifier such as:
# "Asia/Tokyo", "America/New_York", "Europe/London", "UTC", etc.
# To view all available values:
# import pytz; print(pytz.all_timezones)
# Reference:
# IANA database – https://www.iana.org/time-zones
# Wikipedia – https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
shanghai_tz = pytz.timezone("Asia/Shanghai")
data = [
{
"id": i + 1,
"tsz": shanghai_tz.localize(
datetime.datetime(2025, 1, 1, 0, 0, 0) + datetime.timedelta(days=i)
).isoformat(),
"vec": [float(i) / 10 for i in range(4)],
}
for i in range(data_size)
]
client.insert(collection_name, data)
print("Data inserted successfully.")
3단계: 필터링 연산 (Step 3)
TIMESTAMPTZ는 스칼라 비교, 간격 산술, 시간 구성 요소 추출을 지원해요.
TIMESTAMPTZ 필드에서 필터링 연산을 수행하기 전에 다음을 확인하세요.
- 각 벡터 필드에 인덱스를 만들었는지.
- 컬렉션이 메모리에 로드되었는지.
예시 코드 보기
# Create index on vector field
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vec",
index_type="AUTOINDEX",
index_name="vec_index",
metric_type="COSINE"
)
client.create_index(collection_name, index_params)
print("Index created successfully.")
# Load the collection
client.load_collection(collection_name)
print(f"Collection '{collection_name}' loaded successfully.")
타임스탬프 필터링으로 쿼리 (Query with timestamp filtering)
==, !=, <, > 같은 산술 연산자를 사용해요. Milvus에서 사용할 수 있는 산술 연산자의 전체 목록은 Arithmetic operators를 참고하세요.
아래 예시는 2025-01-03T00:00:00+08:00과 같지 않은 타임스탬프(tsz)를 가진 엔티티를 필터링해요.
# Query for entities where tsz is not equal to '2025-01-03T00:00:00+08:00'
expr = "tsz != ISO '2025-01-03T00:00:00+08:00'"
results = client.query(
collection_name=collection_name,
filter=expr,
output_fields=["id", "tsz"],
limit=10
)
print("Query result: ", results)
# Expected output:
# Query result: data: ["{'id': 1, 'tsz': '2024-12-31T16:00:00Z'}", "{'id': 2, 'tsz': '2025-01-01T16:00:00Z'}", "{'id': 4, 'tsz': '2025-01-03T16:00:00Z'}", "{'id': 5, 'tsz': '2025-01-04T16:00:00Z'}", "{'id': 6, 'tsz': '2025-01-05T16:00:00Z'}", "{'id': 7, 'tsz': '2025-01-06T16:00:00Z'}", "{'id': 8, 'tsz': '2025-01-07T16:00:00Z'}", "{'id': 9, 'tsz': '2025-01-08T16:00:00Z'}", "{'id': 10, 'tsz': '2025-01-09T16:00:00Z'}", "{'id': 11, 'tsz': '2025-01-10T16:00:00Z'}"]
위 예시에서,
tsz는 스키마에 정의된TIMESTAMPTZ필드 이름이에요.ISO '2025-01-03T00:00:00+08:00'은 시간대 오프셋을 포함한 ISO 8601 형식의 타임스탬프 리터럴이에요.!=는 필드 값을 해당 리터럴과 비교해요. 지원되는 다른 연산자에는==,<,>=가 있어요.
간격 연산 (Interval operations)
ISO 8601 지속 형식의 INTERVAL 값으로 TIMESTAMPTZ 필드에 산술을 수행할 수 있어요. 이를 통해 데이터를 필터링할 때 타임스탬프에서 일(days), 시(hours), 분(minutes) 같은 기간을 더하거나 뺄 수 있어요.
예를 들어 다음 쿼리는 타임스탬프(tsz)에 0일을 더한 값이 2025-01-03T00:00:00+08:00과 같지 않은 엔티티를 필터링해요.
expr = "tsz + INTERVAL 'P0D' != ISO '2025-01-03T00:00:00+08:00'"
results = client.query(
collection_name,
filter=expr,
output_fields=["id", "tsz"],
limit=10
)
print("Query result: ", results)
# Expected output:
# Query result: data: ["{'id': 1, 'tsz': '2024-12-31T16:00:00Z'}", "{'id': 2, 'tsz': '2025-01-01T16:00:00Z'}", "{'id': 4, 'tsz': '2025-01-03T16:00:00Z'}", "{'id': 5, 'tsz': '2025-01-04T16:00:00Z'}", "{'id': 6, 'tsz': '2025-01-05T16:00:00Z'}", "{'id': 7, 'tsz': '2025-01-06T16:00:00Z'}", "{'id': 8, 'tsz': '2025-01-07T16:00:00Z'}", "{'id': 9, 'tsz': '2025-01-08T16:00:00Z'}", "{'id': 10, 'tsz': '2025-01-09T16:00:00Z'}", "{'id': 11, 'tsz': '2025-01-10T16:00:00Z'}"]
INTERVAL 값은 ISO 8601 지속 구문을 따르요. 예를 들어:
P1D→ 1일.PT3H→ 3시간.P2DT6H→ 2일 6시간.
필터 표현식에서 직접 INTERVAL 산술을 사용할 수 있어요. 예를 들어:
tsz + INTERVAL 'P3D'→ 3일 더하기.tsz - INTERVAL 'PT2H'→ 2시간 빼기.
타임스탬프 필터링으로 검색 (Search with timestamp filtering)
TIMESTAMPTZ 필터링을 벡터 유사도 검색과 결합해 시간과 유사성 모두로 결과를 좁힐 수 있어요.
# Define a time-based filter expression
filter = "tsz > ISO '2025-01-05T00:00:00+08:00'"
res = client.search(
collection_name=collection_name, # Collection name
data=[[0.1, 0.2, 0.3, 0.4]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression using TIMESTAMPTZ
output_fields=["id", "tsz"], # Fields to include in the search results
)
print("Search result: ", res)
# Expected output:
# Search result: data: [[{'id': 10, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-09T16:00:00Z', 'id': 10}}, {'id': 9, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-08T16:00:00Z', 'id': 9}}, {'id': 8, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-07T16:00:00Z', 'id': 8}}, {'id': 7, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-06T16:00:00Z', 'id': 7}}, {'id': 6, 'distance': 0.9759000539779663, 'entity': {'tsz': '2025-01-05T16:00:00Z', 'id': 6}}]]
컬렉션에 벡터 필드가 두 개 이상 있으면 타임스탬프 필터링을 사용해 하이브리드 검색 연산을 수행할 수 있어요. 자세한 내용은 Multi-Vector Hybrid Search를 참고하세요.
고급 사용 (Advanced usage)
고급 사용을 위해 서로 다른 수준(예: 데이터베이스, 컬렉션, 쿼리)에서 시간대를 관리하거나 인덱스를 사용해 TIMESTAMPTZ 필드의 쿼리를 가속화할 수 있어요.
서로 다른 수준에서 시간대 관리 (Manage time zones at different levels)
TIMESTAMPTZ 필드의 시간대를 데이터베이스, 컬렉션, 또는 쿼리/검색 수준에서 제어할 수 있어요.
| 수준 | 파라미터 | 범위 | 우선순위 |
|---|---|---|---|
| 데이터베이스 | timezone |
데이터베이스의 모든 컬렉션에 대한 기본값 | 가장 낮음 |
| 컬렉션 | timezone |
해당 컬렉션의 데이터베이스 기본 시간대 설정을 재정의 | 중간 |
| 쿼리/검색/하이브리드 검색 | timezone |
한 특정 연산에 대한 임시 재정의 | 가장 높음 |
단계별 지침과 코드 샘플은 전용 페이지를 참고하세요.
쿼리 가속화 (Accelerate queries)
기본적으로 인덱스가 없는 TIMESTAMPTZ 필드의 쿼리는 모든 행에 대한 전체 스캔을 수행하며, 대규모 데이터셋에서는 느릴 수 있어요. 타임스탬프 쿼리를 가속화하려면 TIMESTAMPTZ 필드에 STL_SORT 인덱스를 만들어요.
자세한 내용은 STL_SORT를 참고하세요.
더 알아보기 (Learn more)
- STL_SORT — STL_SORT 인덱스
- Nullable & Default — null 및 기본값
- Basic operators — 산술 연산자
- Multi-Vector Hybrid Search — 다중 벡터 하이브리드 검색
- Milvus 공식 문서 — 스키마 관련 자료