In the design of large-scale vector retrieval systems, HNSW (Hierarchical Navigable Small World) has become the benchmark for single-machine performance, but the graph construction mechanism behind it, parameter tuning, and the challenges of scaling to distributed systems constitute a critical gap from prototype to production. This tutorial will delve into the algorithmic core of HNSW, revealing its deep connections with skip lists and Delaunay triangulation, then discuss parameter trade-offs, memory optimization, and gradually transition to sharding, consistency, and near-real-time search in distributed indexes, and finally introduce quantization compression techniques. Through real engineering cases and runnable code, we help advanced readers build retrieval systems with both high recall and low latency.

HNSW Graph Construction Mechanism: From Delaunay Triangulation to Skip List Inspiration

The core idea of HNSW is to use a multi-layer graph structure to simulate a skip list, achieving logarithmic search complexity. Its theoretical foundation stems from Delaunay triangulation: in an ideal case, if we build a triangulation for each data point with its nearest neighbors, then starting from any point, a greedy search along edges can reach the nearest neighbor in O(log n) steps. However, in high-dimensional spaces, the number of edges in a Delaunay triangulation explodes, making it impractical. The inspiration of HNSW is: through a hierarchical graph, each layer is a sparse subset of the layer above, with the bottom layer containing all data points and the top layer having only a few points. Search starts from the top layer, descends layer by layer, and within each layer uses a greedy algorithm (such as NSW's approximate k-nearest neighbor) to approximate the target.

Insertion process: A new element is randomly assigned a maximum level L (following a geometric distribution with probability p=0.5) from the top layer. Starting from the top layer, at each level, the nearest neighbor is found as the entry point, then it proceeds to the next lower layer, and at each level performs an operation similar to NSW's "search + connect". When connecting, the algorithm maintains a fixed-size neighbor list (M bidirectional connections) for each node, and uses heuristic rules (such as selecting points that are closest to the candidate and do not block each other) to maintain the navigability of the graph. This process is equivalent to maintaining an "approximate Delaunay graph" at each layer, but reduces complexity by limiting the degree and layering.

Search process: Starting from the entry point at the top layer, within each layer, a greedy search is performed (selecting neighbors that are closer to the target and have a distance smaller than the current point, until convergence), then it proceeds to the next layer. This "coarse-to-fine" search path selection makes the average lookup require only O(log n) steps. Key engineering details: the efSearch parameter controls the size of the candidate queue (ef value) for each layer during search, while efConstruction controls the candidate queue for each layer during construction, directly affecting the quality of the graph connections.

Core Parameter Tuning: The Art of Trade-offs among M, efConstruction, and efSearch

These three parameters are the performance switches of HNSW, interacting with each other, and directly determining recall, memory usage, and latency. The table below shows recommended values and trade-offs in different application scenarios:

ParameterFunctionEffect of IncreasingTypical Scenario Recommendation
M (maximum connections per layer)Controls the out-degree of the graph and memoryImproves recall, but memory usage O(M*N) and construction time increase; too large can lead to "hub" nodes in the graph, reducing search speedText embeddings (768 dims): 32-64; Image features (2048 dims): 16-32
efConstruction (dynamic candidate set size during construction)Affects the search width during insertionLarger values yield higher graph quality, but construction time can be O(efConstruction^2)High recall requirements: 200-500; Balanced: 100-200
efSearch (dynamic candidate set size during query)Controls search accuracy and speedLarger values increase recall, but latency grows linearly (simplified to O(efSearch) steps)Online low latency: <50; Offline high recall: 200-1000

Tuning strategy: First fix M, then gradually increase efConstruction until recall no longer significantly improves (on a validation set); then set efSearch based on latency targets. For example, in a scenario with 10M data, 768-dimensional vectors, and cosine similarity, M=32, efConstruction=300, efSearch=100 typically achieves over 95% recall (@10) with latency within 5ms (single-threaded). Engineering pitfalls: M too small leads to poor graph connectivity, and search paths easily fall into local optima; efSearch too large amplifies memory bandwidth bottlenecks because each step requires accessing the feature vectors of candidate nodes.

Memory Layout and Cache Friendliness: Optimizing HNSW Node Access Patterns

The search process of HNSW involves random access to graph nodes, leading to low CPU cache hit rates. To improve performance, optimization is needed from both data structure and access pattern perspectives.

  1. Node structure compression: Separate the feature vectors of nodes from the neighbor lists. For example, use Structure of Arrays (SoA) instead of Array of Structures (AoS) to allow continuous reading of the vector part (utilizing cache lines). Use std::vector<float> to store all vectors, and a two-dimensional array of std::vector<uint32_t> for neighbor lists, with each node storing only neighbor IDs.
  2. Memory alignment: Align node data to 64 bytes to ensure a cache line can hold multiple neighbor IDs (e.g., 16 ints). For vectors, use aligned allocation (such as posix_memalign) to support SIMD instructions (like AVX-512) for distance calculations (dot product, L2 distance).
  3. Prefetch: In the search loop, when evaluating the neighbors of the current node, prefetch the features of the next batch of neighbors into L2 cache in advance. Use GCC's __builtin_prefetch or store neighbor vectors in memory order to enable hardware prefetchers.
  4. Graph direction optimization: Since the graph is undirected, search only traverses edges in one direction (from current node to candidate neighbors), which can reduce memory access by half.

Measured data: On an 8-core Xeon, for searching 1 million 128-dimensional vectors (float) with efSearch=100, the unoptimized latency was about 8ms, which dropped to 3.2ms after adopting SoA and prefetching, an improvement of about 2.5 times. Code example: Use Python's numpy and faiss to build HNSW and show how to customize search parameters.

import faiss
import numpy as np

# Generate 1M 128-dimensional vectors
d = 128
xb = np.random.rand(1000000, d).astype('float32')

# Create HNSW index, M=32, efConstruction=200
index = faiss.IndexHNSWFlat(d, 32)
index.hnsw.efConstruction = 200
index.add(xb)

# Perform query, efSearch=64
k = 10
xq = np.random.rand(1, d).astype('float32')
index.hnsw.efSearch = 64
D, I = index.search(xq, k)
print(I)

From Single Machine to Distributed: Design of Sharding Strategies and Routing Mechanisms

When data volume exceeds single-machine memory (e.g., 10 billion vectors), a distributed index must be adopted. The core issue: how to distribute data across multiple nodes and design routing mechanisms to make queries accurate and efficient.

Comparison of sharding strategies:

  • Hash-based sharding: For example, modulo on ID or vector hash, uniformly distributed but cannot exploit data locality; full queries require broadcasting to all shards and merging results (recall can be exact but costly).
  • Range-based sharding: Divide continuous intervals based on a certain dimension of the vector (such as the first PCA dimension), suitable for ordered range queries, but not intuitive for high-dimensional data.
  • Consistent Hashing: Map the entire vector space onto a ring hash ring, each node is responsible for a segment of the arc, queries locate the target region and only search that node and its adjacent nodes (e.g., +1) to handle boundary points. Advantages: small data migration when adding nodes; disadvantages: boundary points may be pruned, leading to recall degradation, requiring overlapping regions or secondary searches.

Routing mechanism: Typically a two-stage strategy is used: first, a coarse-grained index (such as global cluster centers or quantizers) routes the query to a small number of candidate shards, then HNSW search is performed within those shards. For example, using Product Quantization (PQ) coarse quantizers, data is divided into IVF lists, and during query, the nearest nprobe lists are selected based on Voronoi cells. In a distributed environment, these lists can be distributed across different nodes, and the routing layer maintains a metadata table (list ID to node address

mapping).

Engineering pitfalls: hotspot issues — certain popular data causes some nodes to be overloaded. Solution: use consistent hashing with virtual nodes (each physical node maps to multiple virtual nodes) to balance load. Another pitfall is additional latency in query routing: routing decisions must be completed within milliseconds, typically using in-memory routing tables or approximate hashing.

Consistency Models for Distributed Indexes: Balancing Eventual Consistency and Real-time

In distributed systems, how index updates (insertions, deletions, modifications) propagate to all replicas directly affects the freshness of search results. Typically, an eventual consistency model is adopted: updates are first written to the primary node, then asynchronously synced to replicas. But this may lead to queries seeing stale data, affecting user experience. Trade-offs:

ModelReal-timePerformance OverheadImplementation Complexity
Synchronous replication (strong consistency)High, returns only after all replicas are syncedHigh, large write latencyLow (e.g., using Raft or 2PC)
Semi-synchronous (majority)Relatively high, returns after writing to primary, async syncMediumHigh (requires consensus protocol)
Eventual consistency (async replication)Low, brief inconsistency windowLow, fast writesLow

Real systems (e.g., Milvus, Weaviate) commonly adopt eventual consistency plus a version number mechanism: each update is assigned an incrementing version, queries can carry the version number, and if a node's data is too old, retry. Additionally, use read-write separation: primary handles writes, replicas handle reads, and periodically pull incremental updates from primary. For deletions, be careful with tombstones to avoid resurrection.

Engineering solution: Use Apache Kafka or Pulsar as the update log; after writing to primary, publish to the message queue, and all replicas consume and apply changes. Combine with background segment merge to optimize storage. When data scale is huge, you can also use consistent hashing + version vectors to detect conflicts, achieving eventual consistency without monotonic reads.

Near-Real-Time Search: Incremental Index Building and Merge Optimization

To support fast visibility of new data, avoid full index rebuilds. A common approach is incremental segments: divide the index into multiple read-only segments, write new data into a small in-memory index (e.g., a single-layer HNSW graph), and periodically merge with disk segments.

Key point: Bloom Filters are used to quickly determine if a data item is in a segment, avoiding full segment scans. For example, in deletion scenarios, if a committed document is deleted, mark a tombstone in the segment, and queries use the bloom filter to skip segments with no hits.

Merge optimization: Segment merging is I/O intensive; if full merge is used, writes may pause. Use LSM tree style: layer segments, small segments frequently merge into medium ones, medium into large ones, controlling merge granularity. Default configuration: if segment size is below a threshold (e.g., 5GB), do not merge. Also, use faiss's IndexShards or IndexReplicas for parallel merging.

Code example: Use FAISS's IndexShards to implement a simple near-real-time index (add a small index every 1000 items, then merge).

import faiss
import numpy as np

d = 128
shard_size = 1000
n_shards = 10

# Create sharded indexes, each shard is HNSW
shards = [faiss.IndexHNSWFlat(d, 32) for _ in range(n_shards)]
for s in shards:
    s.hnsw.efConstruction = 200
index = faiss.IndexShards(d, True)  # Use 'keep_dirs'?? Here directly use IndexShards for sharding

# Simulate incremental addition and merging
for i in range(10000):
    x = np.random.rand(1, d).astype('float32')
    index.add(x)
    if i % shard_size == shard_size-1:
        # Force merge all shards (in practice use background thread)
        pass

Quantization and Compression: Application of PQ and OPQ in Distributed Vector Search

In distributed systems, vector storage and transmission bandwidth are bottlenecks. Product Quantization (PQ) can compress vectors to 1/16 or even 1/64 of the original size while preserving accuracy. Principle: split the high-dimensional vector into subspaces, each subspace is represented by k cluster centers (codebook), the vector is represented by a set of sub-codes (short ids), and distance is computed by lookup table summation.

Especially OPQ (Optimized Product Quantization) first applies an orthogonal rotation to the vector to balance the variance across subspaces, reducing quantization error. In distributed scenarios, store the codebook and quantized residuals locally; during query, do coarse filtering in the compressed space, then compute exact distances for candidates (re-ranking).

Specific application: In Milvus, you can configure index_type=PQ, with parameters nbits=8 (256 centers per subspace), m=8 or 16. Comparative experiments show that for 1024-dimensional vectors, using PQ (m=16, nbits=8) compresses to 2KB, with only 2-3% recall drop.

Engineering details: Codebook training must be done before index building, typically using a large sample (e.g., 1 million items) to train the codebook, avoiding online updates. Additionally, OPQ's rotation matrix needs to be globally computed and stored, size d*d (e.g., 1024*1024*4 bytes = 4MB), which is acceptable. In distributed settings, each node only stores its local quantized codebook and residual matrix, but the rotation matrix must be consistent, so it's usually globally shared.

The above initially constructs the core indexing mechanism from single-machine to distributed. The following will delve into advanced topics such as distributed query merging strategies, fault recovery, and multi-tenant isolation.

Continuing from the previous analysis of HNSW and distributed index foundations, this section will delve into the fusion architecture, scalability challenges, and core details of engineering implementation, presenting a complete design blueprint that can guide production environments.

Fusion of Graph Index and Inverted Index: Analysis of Hybrid Retrieval Architecture

Sparse retrieval (e.g., BM25) excels at precise keyword matching, while dense retrieval (e.g., vector similarity) captures semantic relationships; they are highly complementary. The goal of hybrid architecture is to utilize both signals in a single query and fuse ranking results. Common strategies include three types:
  • Weighted Reciprocal Rank Fusion (RRF): Take Top-K from both retrieval results, and sum by reciprocal rank: score = Σ 1/(k + rank). Simple and effective, but sensitive to k (usually 60), and does not consider score distribution.
  • Cascade re-ranking: First use sparse or dense retrieval to get a candidate set (e.g., 1000 items), then use the other method or a cross-encoder for fine ranking. Controls cost, but may miss long-tail relevant results.
  • Learned fusion: Use an LTR model (e.g., LambdaMART) with both scores as features to train a ranking model. Best performance, but requires labeled data.
In engineering, we typically have the inverted index and HNSW graph index coexist in the same shard; queries access them in parallel, then do RRF at the coordinator node. Note that the latency of both retrieval paths should be close to avoid waiting for the long tail. Set timeout protection and truncation strategies. The following code shows how to call the DeepSeek API to fuse and rank the two results (simulating two scores in the example):
import requests
import numpy as np

# Simulate sparse and dense scores
sparse_scores = {"doc1": 2.5, "doc2": 1.8, "doc3": 1.2}
dense_scores = {"doc2": 0.9, "doc3": 0.8, "doc1": 0.6}

def rrf_fuse(k=60):
    fused = {}
    for scores in [sparse_scores, dense_scores]:
        for rank, doc in enumerate(sorted(scores, key=scores.get, reverse=True)):
            fused[doc] = fused.get(doc, 0) + 1.0 / (k + rank + 1)
    return sorted(fused.items(), key=lambda x: x[1], reverse=True)

# Call DeepSeek for semantic verification of top results (optional)
def deepseek_rerank(query, docs):
    api_key = "your-deepseek-api-key"
    response = requests.post(
        "https://ap
i.deepseek.com/chat/completions",
        headers={"Authorization": f"Bearer {api_key}"},
        json={
            "model": "deepseek-chat",
            "messages": [
                {"role": "system", "content": "You are a sorting assistant. Please score by relevance and output a JSON array."},
                {"role": "user", "content": f"Query: {query}\nDocuments: {docs}"}
            ]
        }
    )
    # Parse the returned sorting result...
    return response.json()["choices"][0]["message"]["content"]

print(rrf_fuse())MethodAdvantagesDisadvantagesUse CasesRRFNo training required, robustHyperparameter-sensitive, does not utilize scoresCold start, general retrievalCascade re-rankingHigh precision, controllable costCoarse filtering may truncateSufficient recall, high precision requirementLearned fusionHighest upper bound, adaptiveRequires labels, complex tuningHigh traffic, labels easily available

Challenges of Horizontal Scaling: Data Skew and Hotspot Balancing

When the index is distributed across multiple nodes, data is partitioned by ID or vector clustering, which can easily lead to data skew: some shards have data volumes far exceeding the average, causing uneven query latency. Similarly, query hotspots cause a few nodes to handle a large amount of traffic, resulting in resource waste and latency spikes. Solutions fall into two categories:
  • Data skew balancing: Use load-based re-sharding (e.g., dynamically adjusting shard boundaries based on data volume or query frequency), and use virtual nodes in consistent hashing to map physical nodes to multiple virtual positions, smoothing data distribution. For example, for HNSW indexes, partitioning by center point clustering is possible, but overlapping regions must be handled to avoid cross-node queries.
  • Hotspot balancing: Create multiple replicas for hotspot shards and adopt a write-many-read-one strategy, so different queries hit different replicas. Additionally, add a memory cache layer (e.g., LRU) to alleviate high-frequency query pressure. A smarter approach is to predict hotspots based on query logs and migrate replicas in advance.
For example, in a 100-node cluster, if a shard's data volume is 3 times the average, its query latency might spike from 10ms to 100ms, while other nodes are idle. We can design a monitoring controller that periodically collects QPS and CPU per shard, and when the imbalance exceeds a threshold, triggers a rebalancing task to migrate data in a rolling fashion, avoiding downtime. The dynamic balancing shard log can be represented in JSON:
{
  "rebalance_plan": {
    "trigger": "coefficient_of_variation > 0.3",
    "action": "move_shard",
    "source_node": "node-7",
    "target_node": "node-23",
    "shard_ids": ["shard-12", "shard-15"],
    "throttle_limit_mb_per_sec": 50
  }
}

Fault Recovery and Replica Strategies: Ensuring High Availability of Distributed Indexes

Distributed systems must tolerate node failures. Core mechanisms include:
  • Fault detection: Use heartbeats and timeouts (e.g., Raft protocol) to detect node liveness. For memory-resident index structures like HNSW, quick detection of unavailability is needed, typically using streaming heartbeats (every 500ms) combined with TCP probes.
  • Failover: When the primary node fails, elect a new primary from replicas. Data consistency must be ensured: either synchronous writes to primary and backup (strong consistency) or asynchronous replication with tolerance for brief inconsistency. For index systems, eventual consistency is typically adopted, with switchover time controlled to seconds.
  • Replica synchronization: The primary sends write-ahead logs (WAL) asynchronously to replicas, which replay them to update local indexes. To avoid split-brain after network partitions, lease or Quorum mechanisms are introduced.
Replica strategies require trade-offs: more replicas increase fault tolerance but raise write amplification and storage costs. A common strategy is 2 replicas + 1 arbitration replica (i.e., 3 replicas), allowing one node to fail. For critical systems, different replica counts can be set per partition. For example, core indexes use 3 replicas, hot data uses 2 replicas. During switchover, clients need to reconnect via service discovery. The following replica management rules can be designed:
  1. Each shard maintains one leader and two followers.
  2. The leader sends heartbeats every 100ms; followers trigger an election after a 500ms timeout.
  3. During switchover, read-only requests can continue to be served by other replicas, while write requests are temporarily blocked or retried.
  4. Synchronization uses incremental snapshots plus asynchronous logs to ensure eventual consistency.

Performance Evaluation Methodology: Building Benchmarks and Interpreting Metrics

Evaluating a distributed vector retrieval system requires defining clear metrics:
  • Recall@K: The proportion of truly relevant results (e.g., true nearest neighbors obtained by brute-force search) among the retrieved K results.
  • Query throughput (QPS): The number of queries processed per second, measured while ensuring latency constraints.
  • Latency: P50, P95, P99 percentiles, with special attention to P99, reflecting tail performance.
  • Index build time and memory usage: Affects operational costs.
Evaluation method: Use standard test sets (e.g., SIFT, GIST) across different dataset sizes (e.g., 1M, 10M, 100M vectors) and dimensions. The process is as follows:
  1. Warm-up phase: Run 1000 queries to populate caches.
  2. Stress testing: Gradually increase concurrency (e.g., 1, 8, 16, 32, 64) and record latency and QPS.
  3. Compare different parameters (e.g., HNSW's M, efConstruction) and plot Recall-QPS curves to find the Pareto optimum.
Note: In a distributed environment, network bandwidth effects must be considered, and cross-machine latency should be recorded. Evaluation reports should include environment specifications, data distribution, and parameter configurations for reproducibility. For example, on a 10M dataset, HNSW (M=16) achieves Recall@10=0.95 with 5ms latency on a single machine, while with 3 distributed nodes, QPS improves 2.3x but P99 latency increases by 20%.

Engineering Practice: Pitfalls in Migrating from Single-Machine HNSW to Distributed Systems

During migration, engineers often encounter the following pitfalls:
  • Parameter drift: HNSW parameters (e.g., M, efC) that are optimal on a single machine may degrade in distributed settings. Network overhead changes latency distribution, requiring re-tuning. For example, increasing efSearch improves recall but increases cross-node communication, requiring trade-offs.
  • Network overhead: During graph traversal, neighbors may reside on different nodes, causing numerous cross-node requests. Solutions: partition to localize graph edges as much as possible, or use graph pruning to reduce cross-edges.
  • Serialization cost: Use efficient serialization for vectors and graph nodes (e.g., FlatBuffers, Cap'n Proto) to avoid JSON overhead. In practice, ProtoBuf is 3-5x faster than JSON and 30% smaller.
Solutions: Design intra-shard local graphs, and for cross-shard edges, merge results at the coordinator node. Additionally, introduce a cache layer to cache high-frequency node vectors, reducing serialization calls. Key principle: partition data into multiple "independent subgraphs", each capable of handling sub-queries on a single machine, and finally aggregate rankings. Below is a migration self-check list:
  1. Re-evaluate data distribution to avoid single-point hotspots.
  2. Stress-test network round-trips and set reasonable timeouts (e.g., 50ms).
  3. Monitor serialization CPU usage; if it exceeds 30%, optimize encoding.
  4. Gradual rollout, comparing Recall and latency before and after migration to ensure no degradation.

Case Study: Architecture Design and Optimization of a Billion-Scale Vector Retrieval System

A real system (e.g., an e-commerce image search) processes 100 million 128-dimensional vectors, designed as follows:
  • Index layering: The first layer uses Product Quantization (PQ) to compress vectors to 32 bytes for coarse candidate filtering (Recall 80%), and the second layer uses original vectors for fine re-ranking on the candidate set (Recall improves to 95%).
  • Cache layer: For popular query vectors, use Redis to cache Top-K results, achieving a 30% hit rate and reducing load on the underlying system.
  • Query optimization: Use multi-threaded pipelines to overlap vector encoding, network transmission, and distance computation. Use GPUs for batch matrix operations, improving throughput by 5x.
  • Dynamic indexing: For new data, use incremental HNSW merging and periodic rebuilding.
System architecture: Client -> Gateway (load balancing) -> Routing layer (hash by vector ID) -> Index shards (each shard holds 20 million vectors, HNSW) -> Result fusion layer. Before and after optimization comparison:
MetricBeforeAfterImprovement
P99 latency120ms35ms70%
QPS80052005.5x
Memory usage1.2TB0.9TB (PQ)25%
Key takeaways: hierarchical retrieval can significantly reduce costs; hotspot caching yields substantial benefits; use asynchronous batching to reduce network round trips.

Future Trends: Potential of Graph Neural Networks and Learned Indexes in Retrieval

Learned indexes (LII) replace B-trees or hash indexes with neural networks, reducing memory and predicting data distribution. For HNSW, GNNs can be used to learn graph structures, optimize neighbor selection, and improve navigation efficiency. For example, using GraphSAGE to train a model that predicts high-quality neighbors for nodes, thereby building graphs with shorter jumps. Potential includes:
  • Adaptive graph construction: dynamically rewire edges based on query load to improve connectivity in hotspot regions.
  • Approximate distance estimation: use small networks to replace high-dimensional distance computations, accelerating pruning.
  • End-to-end retrieval: embed the index into the retrieval model to directly output Top-K, but current interpretability and stability are insufficient.
The challenges lie in training cost and generalization ability, but under specific distributions (e.g., multimodal data), learned indexes can reduce memory by 30% and improve recall by 20%. The DeepSeek API can be used to generate synthetic training data, for example:
import requests

def generate_training_data(query_pool):
    api_key = "your-deepseek-api-key"
    # Use DeepSeek to generate similar query pairs for training GNN edge prediction
    resp = requests.post("https://api.deepseek.com/chat/completions",
        headers={"Authorization": f"Bearer {api_key}"},
        json={"model": "deepseek-chat", "messages": [{"role": "user", "content": "Generate 10 semantically similar but differently phrased queries, in JSON list format"}], "temperature": 0.7})
    return resp.json()

Summary and Best Practices

  • Architecture design: adopt hybrid retrieval (sparse + dense), fuse with RRF or learned ranking; choose cascade or parallel based on business needs.
  • Scalability: use virtual nodes to balance data skew, dynamically migrate replicas to alleviate hotspots, and set monitoring thresholds to trigger rebalancing automatically.
  • High availability: at least 2 replicas, use Raft for leader election; failover in seconds, async log synchronization.
  • Performance evaluation: fix dataset size, measure Recall, QPS, P99, and plot cost curves; repeat multiple times and take the median.
  • Migration pitfalls: re-tune parameters, use efficient serialization (e.g., FlatBuffers), design locality-aware sharding, and constantly monitor network overhead.
  • Architecture optimization: use PQ for coarse filtering + original vectors for fine ranking; set up cache layers; leverage GPU acceleration for distance computations.
  • Future: pay attention to learned indexes and GNNs, but verify stability and benefits.
Final advice: all optimizations should be based on business metrics; first establish a comprehensive observability system, then iterate gradually. Distributed vector retrieval is essentially a balance between engineering and algorithms; there is no silver bullet, only fine-tuning and architectural evolution.