Refresh a Vector Index
Build a Vector Index for the current source Table version with a durable Task.
Rebuild frame-search after new frames land in frames. A search fails while
the index covers an older Table version, so a refresh is the step that makes
search available again. The build runs as a Task on a
Worker and publishes the new index version in one
commit.
In Studio, the Refresh action on the Vector Index does the same thing. This guide uses the Task directly, which also works from scripts and Automations.
Before you start
- A Vector Index. See Create a Vector Index.
- The branch ID and its head commit ID, and the Resource ID and version ID of
the Vector Index at that commit. See
Select an exact state. The Resource
kind is
vector-index, and the Resource ID is the Vector Index ID. - A Worker Pool that can run Tasks for the Project.
Refreshes produce codec version 3 by default.
The packed_postings engine option accepts "true" to enable codec version 4.
Codec version 4 requires compatible embedded clients and Connect hosts.
Read the current version
Read the version that the commit selects. Its definition names the source Table, and its build state shows the covered source version:
read = client.vector_indexes.read_version(vector_index_id, version_id)
print(f"dimensions: {read.definition.dimensions}")
if read.version.source_version_id is None:
print("not refreshed")
else:
print(f"covers source version: {read.version.source_version_id}")
physical = read.version.physical
print("not built" if physical is None else f"sealed with {physical.indexed_rows} rows")| Field | Meaning |
|---|---|
definition.sourceResourceId | The Catalog Resource ID of the source Table. |
definition.metric, definition.dimensions | The distance metric and the vector length. |
version.sourceVersionId | The source Table version that the build covers. Absent before the first build. |
version.physical | The sealed build, with indexedRows and partitions. Absent before the first build. |
Submit the refresh Task
In an SDK, resolve the Vector Index on a branch and refresh it; the build reads
the source Table's latest version on that branch. Over HTTP, submit a
vectorIndexRefresh definition whose read target names the branch and,
optionally, the exact commit to build from:
index = client.project("demo").branch("main").vector_index("frames_by_embedding")
task = index.refresh(mode="full")
if task is None:
print("a refresh of this Vector Index is already waiting")
else:
print(f"built {task.wait().versions[0].version_id}")vectorIndexId and vectorIndexResourceId take the same value: the Vector
Index's Resource ID. The Task checks your permission under both names. It needs
write permission on the Vector Index and read permission on the source
Table. It uses cpu-2 unless you select another resource profile in
options. It allows three attempts.
Set mode to full. The vortex.ivf-rabitq engine rebuilds the whole index
on every refresh.
The idempotency key makes a retry safe. Use a new key for each new refresh.
Verify the result
- Wait for the Task to reach a terminal status. See Tasks.
- Read
published.versionsandpublished.commitId. Use the result fromwait()in SDK calls. - Read the exact Vector Index version that the result identifies.
- Verify that
version.sourceVersionIdidentifies the refresh source and thatversion.physicalexists. - Read
version.physical.indexedRowsfor the indexed row count.
Troubleshooting
| Problem | Cause |
|---|---|
| The Task stays pending | No Worker can run Tasks for the Project. Check the Worker Pool. |
| The Task fails because the Worker memory budget is too small | The selected resource profile cannot fit the build for these vector dimensions. |
| The build exceeds its posting descriptor limit | The posting buffers cannot fit the index layout. A larger Worker or fewer partitions can reduce the descriptor count. |
| A search still fails as stale | The source Table changed after the commit that the Task read. Refresh again from the new head. |