jvector

datastaxApache-2.0活跃维护

纯 Java 实现的嵌入式向量搜索引擎,支持磁盘索引和增量更新,适合在 JVM 应用里直接做近似最近邻检索,不用额外部署服务。

JVector: the most advanced embedded vector search engine

4.0.2发布于 2026-10-19 19:51 UTC1,757star163fork同步于 2026-11-10 05:52 UTC

怎么上手

由 README 提炼,执行前请确认
mvn compile exec:exec@sift
mvn compile exec:exec@bench
硬件要求按 README 说明

README 未说明显存要求;纯 Java 库,可 CPU 运行。原生 SIMD 库支持 Linux x86-64(SSE4.2/AVX2/AVX-512)与 Linux AArch64(NEON/SVE/SVE2),构建需 g++ 11+。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

Java 嵌入式图向量索引库,融合 HNSW 与 DiskANN,支持超内存规模构建

纯 Java 实现的嵌入式向量搜索引擎,支持磁盘索引和增量更新,适合在 JVM 应用里直接做近似最近邻检索,不用额外部署服务。

核心能力

  • 多层图索引,上层内存邻接表、底层磁盘邻接表
  • 两遍搜索:内存量化粗筛加磁盘精确重排
  • 支持 PQ、BQ、Fused PQ 与 NVQ 量化
  • 非阻塞并发控制,构建随核数线性扩展
  • 可构建大于内存的索引,避免多索引线性合并

容易踩的坑

Bench 会自动下载数据集到 dataset_cache 目录,需联网;原生 SIMD 需加 --add-modules jdk.incubator.vector 和 --enable-native-access=ALL-UNNAMED,否则回退或告警;自行编译原生库需 Meson、Ninja 和 g++ 11+。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本4.0.2
  1. 4.0.2最新正式版2026-10-19 · 2026-10-19 19:51 UTC

    JVector Release Notes

    Version: 4.0.1 - 4.0.2


    New Features

    Added optional batched vector access and a bounded file source for quantizer training, encoding and existing full-precision/NVQ disk serialization. Capable algorithms can consume samples or full scans without requiring an upfront preload of the original base dataset; existing vector sources remain supported.

    BenchYAML and AutoBenchYAML support useDatasetPrefetching: true in their index configuration. The flag defaults to false, preserving resident loading and scoring. Comparison-heavy uncompressed configurations retain resident input. The existing jvector.dataset_loader VM option overrides the flag, while configurations requiring resident raw vectors still preload; an explicit buffered request logs the reason for that fallback.

    See batched vector access for ownership, resource limits, examples and the benchmark opt-in. Encoded vectors, training working memory and graph structures retain their existing memory requirements.


    Google Highway native SIMD is no longer experimental and is preferred by default on supported Java 22+ runtimes. jvector.enable_native_vectorization is the supported flag; the former name remains a deprecated compatibility alias.

    Successful native selection uses MemorySegmentVectorFloat instead of ArrayVectorFloat. Consumers should use VectorFloat, or FloatArray.array() when array access is needed; direct casts and assumptions about get()'s backing storage must be updated. copyFrom supports both built-in float vector types. Disable automatic native selection with -Djvector.enable_native_vectorization=false to retain the previous provider choice. Native operations require provider-created vectors; copying between storage types does not make mixed-storage arithmetic valid.

    Pass --add-modules jdk.incubator.vector --enable-native-access=ALL-UNNAMED for classpath deployments. Missing native access can produce JVM warnings; denied native access, an unsupported ABI, a missing ABI query, or missing required library symbols cause automatic selection to fall back to the Java provider. Explicitly forcing native fails during initialization.

    Java requires ABI 1 and checks the native library's explicit supported set before calling kernels. Compatible native releases keep the same ABI ID. Libraries that predate the ABI query are rejected; the bundled library supports ABI 1.


    Performance Improvements

    Native SIMD Acceleration on AArch64 (NEON, SVE, SVE2)

    PR: #723

    Description

    This PR extends JVector's native Highway SIMD backend to AArch64 (64-bit ARM), bringing the same native acceleration that x86-64 users already have to ARM-based servers and development machines (e.g. AWS Graviton, Apple Silicon under Linux, Ampere Altra).

    AArch64 support was previously absent from the native layer — ARM hosts silently fell back to the Panama Vector API path. The native binary now ships three AArch64 ISA tiers, all compiled as vector-length-agnostic (scalable) code:

    TierHighway targetNotes
    NEONHWY_NEONBaseline; all AArch64 CPUs
    SVEHWY_SVEScalable Vector Extension
    SVE2HWY_SVE2SVE2 + i8mm + bf16

    SVE and SVE2 are compiled as VL-agnostic (scalable) code, so the same binary runs correctly on any SVE/SVE2-capable CPU regardless of its physical vector length. NEON operates on fixed 128-bit vectors. At JVM startup, the best available tier is selected automatically via CPU feature detection — identical to the existing CPUID-based dispatch on x86-64.

    The following changes were made:

    • NativeVectorizationProvider — the hard-coded x86_64 architecture check is extended to include aarch64, so the provider is offered on ARM Linux hosts.
    • jvector_arch.h — new header introd
  2. 4.0.12026-09-18 · 2026-09-18 21:02 UTC
    查看更新说明

    JVector Release Notes

    Version: 4.0.0-rc.9 - 4.0.1


    New Features

    Runtime Configuration for Graph Index Builder (JMX by default, pluggable backend)

    PR: #703

    Description
    Introduces GraphIndexBuilderConfig, a managed singleton that exposes GraphIndexBuilder construction parameters as runtime-tunable attributes. Before this change, options such as addHierarchy, refineFinalGraph, and parallelBuild could only be set at the construction call site and required a code change or application restart to modify. With this change, all parameters — graph topology flags, write path selection, build-time compression type, and PQ compression tuning — can be inspected and updated live, without restarting the JVM.

    Changes take effect the next time a GraphIndexBuilder is constructed; they do not affect indexes that are already being built or have already been built.

    Architecture

    GraphIndexBuilderConfig implements GraphIndexBuilderSettings, a plain domain interface with no dependency on JMX or any other transport, and registers itself with ManagementRegistry (package io.github.jbellis.jvector.management). The registry hands the registration to whichever ManagementBackend is active for the JVM. By default, that's JMX: the io.github.jbellis.jvector.management.jmx.JmxManagementBackend wraps GraphIndexBuilderConfig in a javax.management.StandardMBean and registers it with the platform MBeanServer under the object name io.github.jbellis.jvector:type=GraphIndexBuilderConfig — behaviorally identical to prior releases, so JConsole/jmxterm usage below is unchanged. All attributes are stored as volatile fields so writes from a management-backend thread are immediately visible to application threads without additional synchronization. Registration is best-effort throughout this stack: a failure (for example, in a restricted JVM environment) logs a warning but does not disrupt normal operation — the singleton continues to supply its default values.

    The management backend is selectable per JVM via the jvector.management.backend system property:

    ValueBehavior
    (unset) or jmxJMX (default) — identical to the behavior described below.
    noneNo external exposure. GraphIndexBuilderConfig remains fully usable programmatically; nothing is registered with any transport. Use this where JMX is disallowed.
    a fully-qualified class nameA custom io.github.jbellis.jvector.management.spi.ManagementBackend implementation, loaded reflectively (must have a public no-arg constructor).

    See docs/admin-service-interfaces.md for the full design.

    Managed Attributes

    Graph topology

    AttributeTypeDefaultDescription
    AddHierarchybooleantrueWhen true, builds HNSW-style hierarchy layers on top of the base Vamana graph. false produces a flat level-0 (plain Vamana) index, which uses less memory and may build faster on small datasets.
    RefineFinalGraphbooleantrueWhen true, runs a second diversity-refinement pass over each node's edges after the initial build. Improves recall at the cost of additional build time.

    Write path

    AttributeTypeDefaultDescription
    ParallelBuildbooleanfalseWhen true, serializes level-0 node records concurrently via OnDiskParallelGraphIndexWriter. Both writers produce an identical on-disk format; switching this flag does not require re-indexing existing data.

    Build-time compression

    AttributeTypeDefaultDescription
    BuildCompressionTypeString"NONE"Compression used for scoring during graph construction. Valid values: "NONE" (full-precision), "PQ" (Product Quantization), "BQ" (Binary Quantization).

    PQ build compression parameters — consulted on

  3. 4.0.0-rc.92026-07-21 · 2026-07-21 15:08 UTC
    查看更新说明

    JVector Release Notes

    Version: 4.0.0-RC.8 - 4.0.0-RC.9


    New Features

    Streaming N:1 Graph Index Compaction

    PR: #659

    Description
    OnDiskGraphIndexCompactor merges multiple on-disk HNSW graph indexes into a single compacted index. This targets write-heavy workloads where data is continuously ingested into small segment indexes that accumulate over time; periodically compacting those segments into one larger index improves search throughput and recall without rebuilding from scratch.

    Each source is an OnDiskGraphIndex paired with a FixedBitSet marking its live (non-deleted) nodes. The compactor merges all live nodes into a single graph, remaps each source's ordinals into a contiguous global ordinal space via user-supplied OrdinalMappers, and rebuilds each node's neighbor list using Vamana-style diversity selection over candidates gathered from the node's own source and from graph searches in the other sources. Sources are processed in parallel, batch-by-batch, with a bounded backpressure window so memory stays flat regardless of dataset size.

    Purpose / Impact

    • Consolidates many small segment indexes into one larger index, improving search throughput and recall without a full rebuild
    • Excludes deleted nodes from the output, reclaiming space as part of the merge
    • Bounded heap footprint — compaction streams per-source batches in parallel rather than materializing the full merged graph in memory. All benchmark datasets compact under -Xmx5g, including a 10M-vector, 2560-dimension dataset
    • Measured recall is on par with or better than building a single index from scratch across a range of datasets

    How to Enable
    Construct an OnDiskGraphIndexCompactor from the source indexes, their live-node bitsets, and an ordinal remapper per source, then call compact():

    List<OnDiskGraphIndex> sources = List.of(index0, index1, index2);
    
    // Mark all nodes live (no deletions)
    List<FixedBitSet> liveNodes = sources.stream()
        .map(s -> { var bs = new FixedBitSet(s.size()); bs.set(0, s.size()); return bs; })
        .collect(toList());
    
    // Sequential ordinal remapping: source[s] node i -> global offset[s] + i
    int offset = 0;
    List<OrdinalMapper> remappers = new ArrayList<>();
    for (var src : sources) {
        remappers.add(new OrdinalMapper.OffsetMapper(offset, src.size()));
        offset += src.size();
    }
    
    var compactor = new OnDiskGraphIndexCompactor(
        sources, liveNodes, remappers,
        VectorSimilarityFunction.COSINE,
        /* executor= */ null                  // null = use the core JVector thread pool
    );
    
    compactor.compact(Path.of("compacted.index"));
    

    Deleted nodes are dropped by clearing their bit in the corresponding FixedBitSet and remapping only the surviving ordinals (for example with OrdinalMapper.MapMapper).

    Notes

    • The public compactor API is marked @Experimental and may change in a future release.
    • Quantization is preserved across the merge. For FUSED_PQ sources the PQ codes are stored inline and the codebook is retrained on the combined dataset; non-fused sources can supply a sidecar CompressedVectors that is retrained and rewritten as a single merged file.
    • PQ retraining uses balanced proportional sampling across all sources (up to ProductQuantization.MAX_PQ_TRAINING_SET_SIZE vectors total, at least 1000 per source).
    • A new CompactorBenchmark (in benchmarks-jmh) measures compaction time, heap footprint, recall, and search latency. See docs/compaction.md for the full algorithm description and benchmarking instructions.

    Performance Improvements

    Fixes https://github.com/datastax/jvector/issues/629.

    This pull request simplifies AVX-512 feature detection logic in the jvector_simd_check.c file by replacing manual CPUID bit checks with built-in compiler functions (available only on gcc and llvm compilers). The earlier code was missing X

  4. 4.0.0-rc.8-hf1Hotfix 1 for 4.0.0-rc.8pre-release2026-06-19 · 2026-06-19 06:02 UTC
    查看更新说明

    Hotfix 1 for 4.0.0-rc.8

    • Addresses destructive recall caused by usePruning by disabling it (Closes #678)

    For the full release notes of the base release, see 4.0.0-rc.8.

  5. 4.0.0-rc.82026-04-03 · 2026-04-03 21:14 UTC
    查看更新说明

    JVector Release Notes

    Version: 4.0.0-rc.7 - 4.0.0-rc.8


    New Features and Enhancements

    Fused Product Quantization (Fused PQ)

    Description
    Fused Product Quantization (Fused PQ) is a performance optimization that embeds compressed Product Quantization (PQ) codes directly into the graph index structure alongside each node's neighbor lists. This eliminates the need for separate lookups to retrieve compressed vectors during graph traversal, significantly improving query performance by reducing memory access overhead. The feature stores PQ-encoded neighbor vectors inline with the graph edges, enabling faster approximate similarity scoring during search operations. By embedding the compressed neighbor vectors into the graph index itself, Fused PQ eliminates the need to maintain a separate in-memory data structure for PQ-encoded vectors, reducing heap memory usage while maintaining fast approximate similarity search performance.​

    Purpose / Impact

    • Reduces memory usage for large-scale vector datasets
    • Improves cache locality during graph traversal
    • Enables higher writer scalability for large / high-dimensional vector workloads

    How to Enable
    To enable Fused PQ when writing an on-disk graph index:

    1. Create the FusedPQ feature by passing your graph's max degree and a ProductQuantization compressor to the constructor:

      var fusedPQFeature = new FusedPQ(graph.maxDegree(), pq);
      
    2. Add it to your OnDiskGraphIndexWriter builder:

      var writer = new OnDiskGraphIndexWriter.Builder(graph, outputPath)
          .with(fusedPQFeature)
          .build();
      
    3. Provide a state supplier during the write phase that includes the graph view and PQ vectors:

      Map<FeatureId, IntFunction<Feature.State>> writeSuppliers = new EnumMap<>(FeatureId.class);
      writeSuppliers.put(FeatureId.FUSED_PQ, ordinal -> new FusedPQ.State(view, pqVectors, ordinal));
      writer.write(writeSuppliers);
      

    Notes

    • Fused PQ requires a 256-cluster ProductQuantization compressor. The feature automatically embeds compressed neighbor vectors inline with the graph structure during the write operation.
    • To enable the FUSED_PQ feature, we introduced the new version 6 file format for our graph indices.

    Parallel Graph Index Construction

    Description
    OnDiskParallelGraphIndexWriter significantly accelerates graph index construction by addressing the disk I/O bottleneck that limits the serial OnDiskGraphIndexWriter. This implementation uses asynchronous file I/O with multiple worker threads to write graph records in parallel, with parallelism automatically determined by available system resources (or configurable via builder options). By parallelizing both record building and disk writes while maintaining correct ordering, this approach dramatically reduces the time required to persist large graph indexes to disk.

    Purpose / Impact

    • Eliminates i/o bottleneck in on disk graph construction
    • Maintains backwards compatibility for existing clients of the JVector library

    How to Enable
    To enable parallel graph index writes, simply use OnDiskParallelGraphIndexWriter.Builder instead of OnDiskGraphIndexWriter.Builder:

    Basic usage (uses default parallelism based on available processors):

    try (var writer = new OnDiskParallelGraphIndexWriter.Builder(graph, outputPath)
            .with(features...)
            .build()) {
        writer.write(featureSuppliers);
    }
    

    Advanced configuration:

    try (var writer = new OnDiskParallelGraphIndexWriter.Builder(graph, outputPath)
            .with(features...)
            .withParallelWorkerThreads(8)           // Optional: specify thread count (0 = auto)
            .withParallelDirectBuffers(true)        // Optional: use direct ByteBuffers for better performance
            .build()) {
        writer.write(featureSuppliers);
    }
    

    The parallel wr

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Introduction to approximate nearest neighbor search

    Exact nearest neighbor search (k-nearest-neighbor or KNN) is prohibitively expensive at higher dimensions, because approaches to segment the search space that work in 2D or 3D like quadtree or k-d tree devolve to linear scans at higher dimensions. This is one aspect of what is called “the curse of dimensionality.”

    With larger datasets, it is almost always more useful to get an approximate answer in logarithmic time, than the exact answer in linear time. This is abbreviated as ANN (approximate nearest neighbor) search.

    There are two broad categories of ANN index:

    Graph-based indexes tend to be simpler to implement and faster, but more importantly they can be constructed and updated incrementally. This makes them a much better fit for a general-purpose index than partitioning approaches that only work on static datasets that are completely specified up front. That is why all the major commercial vector indexes use graph approaches.

    JVector is a graph index that merges the DiskANN and HNSW family trees. JVector borrows the hierarchical structure from HNSW, and uses Vamana (the algorithm behind DiskANN) within each layer.

    JVector Architecture

    JVector is a graph-based index that builds on the HNSW and DiskANN designs with composable extensions.

    JVector implements a multi-layer graph with nonblocking concurrency control, allowing construction to scale linearly with the number of cores: JVector scales linearly as thread count increases

    The upper layers of the hierarchy are represented by an in-memory adjacency list per node. This allows for quick navigation with no IOs. The bottom layer of the graph is represented by an on-disk adjacency list per node. JVector uses additional data stored inline to support two-pass searches, with the first pass powered by lossily compressed representations of the vectors kept in memory, and the second by a more accurate representation read from disk. The first pass can be performed with

    The second pass can be performed with

    • Full resolution float32 vectors
    • NVQ, which uses a non-uniform technique to quantize vectors with high-accuracy

    This two-pass design reduces memory usage and reduces latency while preserving accuracy.

    Additionally, JVector is unique in offering the ability to construct the index itself using two-pass searches, allowing larger-than-memory indexes to be built: Much larger indexes

    This is important because it allows you to take advantage of logarithmic search within a single index, instead of spilling over to linear-time merging of results from multiple indexes.

    Getting started with JVector

    Introductory tutorials for JVector are available in docs/tutorials. Start with the basic tutorial or review VectorIntro.java for a simple example using JVector.

    For file-backed input datasets, see Batched input vector access, including runnable 100k-vector examples and optional integration with PQ and NVQ.

    For writing completed graphs with FP or NVQ features, see Deferred batch serialization. It works with application vector sources and preloaded data; dataset prefetching is optional.

    The older step-by-step guide for JV can be found here. New users should start with the tutorials mentioned earler, but the step-by-step guide contains useful commentary for advanced users.

    SIMD provider selection

    On Java 22+ with the Vector API enabled, JVector automatically prefers its Google Highway native provider when the native library is available. Native libraries are bundled for Linux x86-64 (SSE4.2 or newer) and Linux AArch64. Use these JVM options:

    --add-modules jdk.incubator.vector
    --enable-native-access=ALL-UNNAMED
    

    Omitting native access can produce restricted-method warnings. If native access is denied by the runtime or JVM options, automatic selection falls back to Panama; an explicitly forced native provider fails during initialization. For named-module deployments, enable native access for the module containing JVector's native code.

    Operations implemented by Highway use native kernels; remaining operations use the inherited Panama/Java Vector API implementation with native vector storage. Native ISA selection remains automatic and respects the existing JVECTOR_MAX_ISA cap.

    JVM propertyEffect
    No provider propertyPrefer native on Java 22+; use Panama when native is unavailable
    -Djvector.enable_native_vectorization=falseDisable automatic native selection
    -Djvector.vectorization_provider=panamaExplicitly select Panama
    -Djvector.vectorization_provider=nativeExplicitly require native; fail if it cannot load
    -Djvector.vectorization_provider=defaultExplicitly select the scalar provider

    The explicit jvector.vectorization_provider property takes precedence over the native-enable property. The former jvector.experimental.enable_native_vectorization name is a deprecated compatibility alias; the new jvector.enable_native_vectorization name takes precedence when both are supplied. Both names default to true when neither is supplied. Provider selection happens once per JVM. Java 20/21 uses Panama when available. Older runtimes, or runtimes without the Vector API module, retain the scalar fallback. Neither Panama nor native is enabled by these defaults when the existing runtime compatibility checks reject SIMD support.

    Native selection also changes the concrete vector type to MemorySegmentVectorFloat. Use the VectorFloat interface instead of casting to ArrayVectorFloat or assuming that VectorFloat.get() returns a float[]. Both built-in float vector types support FloatArray.array() for array access and copyFrom between their storage types. Native vector operations still require vectors created by the selected provider; copy external vectors into provider-created vectors before passing them to those operations. To retain the previous provider and storage choice, disable automatic native selection with -Djvector.enable_native_vectorization=false.

    The research behind the algorithms

    Developing and Testing

    This project is organized as a multimodule Maven build. The intent is to produce a multirelease jar suitable for use as a dependency from any Java 11 code. When run on a Java 20+ JVM with the Vector module enabled, optimized vector providers will be used. In general, the project is structured to be built with JDK 20+, but when JAVA_HOME is set to Java 11 -> Java 19, certain build features will still be available.

    Cloning

    This repository uses a Git submodule for Google Highway, located at jvector-native/src/main/native/third_party/highway. After cloning, initialise it with:

    git submodule update --init
    

    Or clone with submodules in one step:

    git clone --recurse-submodules <repo-url>
    

    Building native libraries

    The native SIMD library (libjvector.so) is built with Meson + Ninja and requires g++ 11+. Supported platforms: Linux x86-64 (SSE4.2, AVX2, AVX-512) and Linux AArch64 (NEON, SVE, SVE2). The entry-point script is jvector-native/src/main/native/src/build_native_lib.sh. Run it from that directory.

    cd jvector-native/src/main/native/src
    bash build_native_lib.sh
    

    On a fresh Ubuntu machine you can install all required dependencies (g++, meson, ninja) and build in one step:

    cd jvector-native/src/main/native/src
    bash build_native_lib.sh --auto-install-deps
    

    For other distributions the script will print the install commands needed. See jvector-native/src/main/native/README.md for full build options, Maven integration, ISA dispatch details, and how to add new kernels. The native ABI compatibility guide explains the supported ABI set, startup checks, and how to preserve compatibility when changing native entry points.


    Base code is in jvector-base and will be built for Java 11 releases, restricting language features and APIs appropriately. Code in jvector-twenty will be compiled for Java 20 language features/APIs and included in the final multirelease jar targeting supported JVMs. jvector-multirelease packages jvector-base and jvector-twenty as a multirelease jar for release. jvector-examples is an additional sibling module that uses the reactor-representation of jvector-base/jvector-twenty to run example code. jvector-tests contains tests for the project, capable of running against both Java 11 and Java 20+ JVMs.

    To run tests, use mvn test. To run tests against Java 20+, use mvn test. To run tests against Java 11, use mvn -Pjdk11 test. To run a single test class, use the Maven Surefire test filtering capability, e.g., mvn -Dsurefire.failIfNoSpecifiedTests=false -Dtest=TestNeighborArray test. You may also use method-level filtering and patterns, e.g., mvn -Dsurefire.failIfNoSpecifiedTests=false -Dtest=TestNeighborArray#testRetain* test. (The failIfNoSpecifiedTests option works around a quirk of surefire: it is happy to run test with submodules with empty test sets, but as soon as you supply a filter, it wants at least one match in every submodule.)

    You can run SiftSmall and Bench directly to get an idea of what all is going on here. Bench will automatically download required datasets to the dataset_cache directory. The files used by SiftSmall can be found in the siftsmall directory in the project root.

    To run either class, you can use the Maven exec-plugin via the following incantations:

    mvn compile exec:exec@bench

    or for Sift:

    mvn compile exec:exec@sift

    Bench takes an optional benchArgs argument that can be set to a list of whitespace-separated regexes. If any of the provided regexes match within a dataset name, that dataset will be included in the benchmark. For example, to run only the glove and nytimes datasets, you could use:

    mvn compile exec:exec@bench -DbenchArgs="glove nytimes"

    To run Sift/Bench without the JVM vector module available, you can use the following invocations:

    mvn -Pjdk11 compile exec:exec@bench

    mvn -Pjdk11 compile exec:exec@sift

    The ... -Pjdk11 invocations will also work with JAVA_HOME pointing at a Java 11 installation.

    For more information on running benchmarks, go through docs/benchmarking.md.

    To release, configure ~/.m2/settings.xml to point to OSSRH and run mvn -Prelease clean deploy.