Repository navigation
vchord 1.2.0 is the first release of the PGSTY-maintained vchord, based on VectorChord 1.1.1. It focuses on correctness, crash safety and security fixes, and supports PostgreSQL 14–18. This fork is distributed under AGPL-3.0-only.
Upgrading
- Install the new packages and restart PostgreSQL (
vchordmust stay inshared_preload_libraries). - In each database:
ALTER EXTENSION vchord UPDATE TO '1.2.0';
Upgrades from 0.5.3, 1.0.0, 1.1.0 and 1.1.1 produce the same schema as a fresh 1.2.0 install. The index on-disk format is unchanged, so existing indexes keep working without a rebuild. REINDEX is recommended in these cases:
halfvecindexes built on fp16-capable CPUs (ARM with fp16, or x86 with AVX512-FP16) whose values have large magnitudes. Distance reductions used to accumulate in binary16 and overflow, which degraded recall (for example 0.13 instead of 1.00 forhalfvec(784)with values 0–255).- Indexes containing zero vectors or 1-dimensional vectors. Their RaBitQ metadata was NaN; on ARM a
vchordrqindex never returned a stored zero vector. vchordgcosine indexes containing zero vectors. Normalizing a zero vector produced NaN, so they ranked first.
Security
vchordrq_sampled_values,vchordrq_sampled_queriesand the prewarm functions opened an index without any privilege check, so any role could read other users' sampled query vectors once query sampling was enabled. They now require table ownership orSELECTon the table (orpg_read_all_statsfor sampled data), and thevchordrq_sampled_queriesview hides indexes the caller cannot read.- External index build quotes the pgvector schema and table identifiers.
Crash and resource fixes
- Scans abandoned by an aborted subtransaction (
SAVEPOINT, PL/pgSQL exception blocks, cursors in failed portals) no longer release PostgreSQL resources twice; Rust-owned objects are freed without touching released resources. - Cleanup during error unwinding and after aborted scans no longer raises
ResourceOwnerForgeterrors. - External build: a centroid table with a long parent chain overflowed the stack and crashed the server; tree depth is now limited and cycles are reported.
- Internal build: the sample buffer was sized from option upper bounds and an allocation failure aborted the process. It is now capped by the row count, reserved fallibly (
ERRORinstead of abort), and builds whose centroid working set exceedsmaintenance_work_memare refused. vchordgrejects an emptyalphalist instead of panicking.
Wrong results
- PostgreSQL 17+: with the default
io_rerank = read_stream, an item that stopped early (for example a vector freed by a concurrentVACUUM) left its buffers queued, and later items were silently dropped. A cursor paused across aVACUUMreturned 3 of 1,999 remaining rows. vchordgreturned deleted rows (and permanently the start vertex) afterVACUUM, pointing at reused heap TIDs.vchordgsphere predicates (<<->>,<<=>>) compared the internal distance with the radius.- Internal k-means sampling now uses an MVCC snapshot, so dead tuples with reclaimed TOAST values are not read.
rabitq8/rabitq4:v <-> vreturned NaN for about a third of inputs; NaN distances now sort last on every CPU.- MaxSim with partial probes and the default
maxsim_refine = 0: documents missing from a query vector's candidates scored-infand sorted first; they now get the worst candidate distance. rabitq4accepted 65,536–131,070 dimensions and stored rows that could not be read back (breakingSELECT,COPYandpg_dump).
Durability, statistics and planning
- New
vchordgpages andvchordrqtape pages are initialized and WAL-logged before they are linked; a crash in between could leave a chain pointing at an all-zero page. - A stale free space map hit no longer writes an empty WAL record and full-page image.
CREATE INDEX/REINDEXreport real statistics instead of resetting the table'sreltuplesto 0.ANALYZEno longer runs index cleanup, which rewrote the whole index to WAL.- A
vchordgindex (partial, or full afterVACUUM ANALYZEthrough an index-only scan) is no longer chosen for queries without a vector clause such ascount(*). vchordrqcost estimation accounts forLIMITand for filtered scans.- A
probescount that does not match the index disables the index path at planning time, so other plans remain usable; the error is raised only if the index scan runs.
Behaviour changes
probesis validated when it is set: each value must be in1..=4294967295, empty entries and spaces inside a value are rejected, and one trailing comma is accepted for compatibility with 1.1.1.rabitq4/rabitq8text and binary input rejectrabitq4codes above 15, trailing garbage and truncated binary input. Everything earlier versions produced is still accepted, including non-finite metadata, so existing dumps restore.quantize_to_rabitq*raises an overflow error instead of storing non-finite metadata.- Parallel index builds follow PostgreSQL's planner (
plan_create_index_workers); previously any table reloption disabled them. vchordrq_evaluate_query_recallno longer leaks itsSET LOCALsettings into the caller's transaction, and derives ground-truth probes from the index.sphere()is bound at creation time and no longer resolves types through the caller'ssearch_path.halfvecsquared L2 distance on ARM is about 2× slower than in 1.1.1, in exchange for exact accumulation.
Upgrade and packaging fixes
- The compatibility stubs for the 0.2.0–1.0.0 scripts were exported under the wrong names, so
pg_upgradeof such databases failed. All C symbols referenced by shipped SQL scripts are exported again. sql/install/vchord--1.1.1.sqlis restored to the published 1.1.1 script, so fresh and upgraded 1.1.1 installs match.- Debian packages declare the pgvector dependency; release assets ship with
.sha256files.
Also included
- Upstream VectorChord changes since 1.1.1: more f16 SIMD routines, WHPG compatibility, deferred creation of the stats database, and dependency updates.
- pgrx 0.19.3.
- PostgreSQL 19 RC1 builds from source with the
pg19feature for development validation. It is not part of the CI or release matrix.
Known issues
- MaxSim accuracy is low with the default
maxsim_refine = 0; raise it for multi-vector retrieval. vchordrqVACUUMholds a lock that can block the table during index maintenance.- Query sampling can delay a query by up to 5 seconds.
- Upgrading from 1.0.0 or earlier drops
scalar8columns. - The rewritten SVE-512 kernels are not dispatched until validated on SVE-512 hardware; the AVX512-FP16 and SVE paths are tested under emulation only.
- Index scans can return rows out of distance order.
vchordgkeeps searching while it returns rows; a largervchordg.ef_searchmakes this rarer but does not rule it out.halfvecindexes can swap rows whose distances differ by about 0.0001 (vchordrqwithhalfvec_cosine_ops, and everyvchordghalfvecopclass). When strict order matters, re-sort the ANN candidates in an outer query (#17).
Full changelog: 5b87b88...1.2.0