Back to Blog

Doris HNSW Vector Search: Vector Retrieval in an Analytical Database

Apache Doris 2.1+ natively supports HNSW vector indexes, enabling enterprises to perform vector retrieval and traditional OLAP analytics in the same database without maintaining a separate vector database. This article details the HNSW algorithm, vector table design in Doris, index parameter tuning, hybrid query optimization (vector + scalar filtering), and performance comparisons with standalone vector databases.

CoomiaPublished on February 3, 20266 min read
Share this articleTwitter / X

Series: S13 AI Engineering · Article 4 | Level: Advanced | Reading Time: 18 min

Doris HNSW Vector Search: Vector Retrieval in an Analytical Database

#TL;DR

Apache Doris 2.1+ natively supports HNSW vector indexes, enabling enterprises to perform vector retrieval and traditional OLAP analytics in the same database without maintaining a separate vector database. This article details the HNSW algorithm, vector table design in Doris, index parameter tuning, hybrid query optimization (vector + scalar filtering), and performance comparisons with standalone vector databases.

#1. Why Vector Search in Doris

#1.1 The Value of Unified Storage

Traditional RAG architectures require two storage systems -- a vector database (Milvus, Pinecone) for semantic retrieval and an OLAP database (Doris) for structured analytics. This creates triple problems: data consistency, operational complexity, and cost.

Doris's vector search capability lets enterprises support with a single system:

  • Semantic retrieval: Document search based on vector similarity
  • Structured filtering: Precise filtering based on metadata
  • Aggregation analytics: Statistical analysis of retrieval results
  • Real-time updates: Consistency between real-time writes and retrieval

#1.2 When to Choose Doris vs Dedicated Vector DB

ScenarioVector DBDoris Vector SearchRecommendation
Pure vector retrieval, 100M+ scaleOptimalViableVector DB
Vector + complex scalar filteringLimitedOptimalDoris
Vector retrieval + OLAP analyticsNeeds two systemsNativeDoris
Sub-10M scale, simplified archOverkillOptimalDoris

#2. HNSW Algorithm Deep Dive

#2.1 Hierarchical Navigable Small World Graph

HNSW (Hierarchical Navigable Small World) is the most popular approximate nearest neighbor (ANN) search algorithm. Its core idea is building a multi-layer skip-list-like graph index:

Code
Layer 3:  [A] ---------------------- [F]
Layer 2:  [A] ---- [C] ------------ [F] ---- [H]
Layer 1:  [A] - [B] - [C] - [D] - [F] - [G] - [H]
Layer 0:  [A] [B] [C] [D] [E] [F] [G] [H] [I] [J]

Search starts from the highest layer, performs greedy search at each layer, descends layer by layer, and finally finds nearest neighbors at the bottom layer.

#2.2 Core Parameters

ParameterDescriptionRecommended Range
MMax connections per node12-48 (default 16)
ef_constructionBuild-time search width100-500 (must >= 2*M)
ef_searchQuery-time search width64-512 (must >= top_k)
  • Higher M: better recall, slower build, more memory
  • Higher ef_construction: better index quality, slower build
  • Higher ef_search: better recall, slower query (tunable at query time)

#2.3 Performance Characteristics

Dataset SizeBuild TimeMemoryRecall@10QPS
1M (128d)~5 min~1.5 GB98.5%~2000
10M (128d)~60 min~15 GB97.8%~1500
100M (128d)~12 hrs~150 GB96.5%~800

#3. Vector Table Design in Doris

#3.1 Creating a Vector Table

SQL
CREATE TABLE knowledge_base (
    doc_id VARCHAR(64) NOT NULL,
    chunk_id INT NOT NULL,
    content TEXT,
    embedding ARRAY<FLOAT> NOT NULL,
    source VARCHAR(256),
    category VARCHAR(64),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_embedding (embedding) USING INVERTED
        PROPERTIES(
            "index_type" = "hnsw",
            "dim" = "768",
            "metric_type" = "cosine",
            "M" = "16",
            "ef_construction" = "200"
        )
) ENGINE=OLAP
DUPLICATE KEY(doc_id, chunk_id)
DISTRIBUTED BY HASH(doc_id) BUCKETS 16;

#3.2 Inserting Vector Data

SQL
INSERT INTO knowledge_base (doc_id, chunk_id, content, embedding, source, category)
VALUES (
    'doc-001', 1,
    'Apache Doris is a modern MPP analytical database...',
    [0.023, -0.156, 0.089, ...],  -- 768-dimensional embedding
    'technical-docs',
    'database'
);

#3.3 Vector Search Queries

SQL
-- Basic vector search
SELECT doc_id, chunk_id, content,
       cosine_distance(embedding, [0.031, -0.142, ...]) AS distance
FROM knowledge_base
ORDER BY distance ASC
LIMIT 10;

-- Hybrid search: vector + scalar filtering
SELECT doc_id, content,
       cosine_distance(embedding, [0.031, -0.142, ...]) AS distance
FROM knowledge_base
WHERE category = 'database'
  AND created_at > '2025-01-01'
ORDER BY distance ASC
LIMIT 10;

#4. Hybrid Query Optimization

#4.1 Pre-Filter vs Post-Filter

SQL
-- Pre-filter (recommended): scalar filter first, then vector search
-- More efficient when scalar filter is highly selective
SELECT doc_id, content, cosine_distance(embedding, ?) AS dist
FROM knowledge_base
WHERE category = 'database'  -- Scalar filter applied first
ORDER BY dist ASC
LIMIT 10;

-- Post-filter: vector search first, then scalar filter
-- Better when scalar filter is not very selective
SELECT * FROM (
    SELECT doc_id, content, category,
           cosine_distance(embedding, ?) AS dist
    FROM knowledge_base
    ORDER BY dist ASC
    LIMIT 100  -- Retrieve more candidates
) t
WHERE category = 'database'
LIMIT 10;

#4.2 Performance Tuning for Hybrid Queries

SQL
-- Adjust ef_search at query time for recall/speed tradeoff
SET session.hnsw_ef_search = 256;  -- Higher for better recall

-- Use BITMAP index on scalar columns for faster filtering
ALTER TABLE knowledge_base
ADD INDEX idx_category (category) USING BITMAP;

#5. Integration with coomia-dip RAG Pipeline

Python
from ontology_sdk import OntoPlatform

platform = OntoPlatform(base_url="http://localhost:8080", token="admin-token")

# Register vector-enabled object type
platform.ontology.create_object_type(
    name="KnowledgeChunk",
    properties={
        "chunkId": {"type": "STRING", "primary_key": True},
        "content": {"type": "STRING"},
        "embedding": {"type": "VECTOR", "dimension": 768},
        "source": {"type": "STRING"},
        "category": {"type": "STRING"},
    },
    vector_config={
        "embedding_field": "embedding",
        "index_type": "HNSW",
        "metric_type": "COSINE",
        "M": 16,
        "ef_construction": 200,
    },
)

# Semantic search via OQL
results = platform.oql.execute("""
    SELECT chunkId, content, VECTOR_DISTANCE(embedding, $1) AS score
    FROM KnowledgeChunk
    WHERE category = 'technical'
    ORDER BY score ASC
    LIMIT 5
""", params=[query_embedding])

#6. Benchmarks: Doris vs Standalone Vector DB

MetricMilvus 2.3Doris 2.1 HNSWNotes
Pure vector QPS (1M)~3000~2000Milvus optimized for pure vector
Hybrid query QPS~500~1500Doris excels at hybrid queries
Insert throughput~10K/s~50K/sDoris batch write is faster
Storage efficiency1x0.7xDoris columnar compression
Ops complexityHigh (separate system)Low (unified)Doris is already there

#7. Production Best Practices

  1. Dimension selection: 768d (BERT) or 1536d (OpenAI) most common; avoid > 2048d
  2. Normalize vectors: Use cosine similarity with L2-normalized vectors
  3. Batch ingestion: Use Stream Load for bulk vector data import
  4. Monitor index build: HNSW index build is CPU-intensive; schedule during off-peak
  5. Tune ef_search per query: Lower for speed-critical, higher for recall-critical
  6. Partition by time: If data has temporal dimension, partition for efficient pruning

#Summary

This article covered vector search capabilities in Apache Doris: HNSW algorithm fundamentals, vector table design, hybrid query optimization, integration with coomia-dip RAG pipelines, and performance benchmarks. For enterprises already using Doris as their OLAP database, adding vector search eliminates the need for a separate vector database, simplifying architecture while maintaining competitive performance.

Next: [S13-05] Incremental Indexing & Real-Time Vector Updates Previous: [S13-03] Embedding Pipeline Architecture