Apache Doris Deep Practice (Part 2): Vector Index + Inverted Index
In coomia-dip's earlier architecture designs, we initially considered the typical multi-engine approach:
“Series: S8 Technology Deep Dives · Article 2 | Level: Advanced | Reading Time: 20 min
Apache Doris Deep Practice (Part 2): Vector Index + Inverted Index
#TL;DR
- Doris 2.1+ natively supports HNSW vector indexes and inverted indexes, enabling coomia-dip to achieve semantic search and full-text retrieval without deploying standalone Milvus/Elasticsearch
- Sub-second full-text search via inverted indexes replaces the traditional Elasticsearch approach, achieving < 300ms search latency on 50 million Ontology description documents
- The hybrid query combining vector index + inverted index + OLAP analytics is coomia-dip's core differentiating capability; this article details configuration, tuning, and production practices
#1. The Value of a Unified Engine
#1.1 Pain Points of Traditional Approaches
In coomia-dip's earlier architecture designs, we initially considered the typical multi-engine approach:
OLAP Analytics → ClickHouse / Doris
Full-text Search → Elasticsearch
Vector Semantic → Milvus / Pinecone
This approach has three core pain points:
- Data consistency: The same data needs to be synchronized to three engines; latency and consistency are hard to guarantee
- Operational complexity: Deployment, monitoring, upgrades, and backups for three clusters
- Query fragmentation: Hybrid queries (e.g., "find data from the last 30 days that is similar to a vector and contains specific keywords") require multiple queries and result merging at the application layer
#1.2 Doris 2.1+ Unified Capabilities
Doris 2.1 introduced vector indexes and inverted indexes, enabling a single engine to satisfy all three requirements:
| Capability | Implementation | Performance |
|---|---|---|
| OLAP Analytics | Columnar + vectorized execution + MPP | Sub-second aggregation |
| Full-text Search | Inverted Index (CLucene-based) | < 300ms |
| Vector Search | HNSW Index | < 200ms (Top-100) |
#1.3 Application Scenarios in coomia-dip
| Scenario | Index Used | Example |
|---|---|---|
| Ontology object search | Inverted index | Search all objects with "supply chain" in name or description |
| Semantic similar object discovery | Vector index | Find Actions semantically similar to "supply chain risk assessment" |
| Hybrid intelligent search | Inverted + vector + OLAP | Find recently created objects matching user query semantically and by keyword |
| Knowledge base Q&A | Vector index | Retrieve most relevant knowledge fragments in RAG scenarios |
| Anomaly detection assistance | Vector index | Find historical records most similar to anomaly sample embeddings |
#2. Inverted Index Deep Analysis
#2.1 Inverted Index Architecture
Doris's inverted index is built on CLucene (C++ implementation of Lucene), tightly integrated with columnar data:
┌──────────────────────────────────────┐
│ Doris Segment │
│ ┌─────────────┬──────────────────┐ │
│ │ Column Data │ Inverted Index │ │
│ │ (Columnar) │ (CLucene) │ │
│ │ │ ┌──────────────┐ │ │
│ │ tenant_id │ │ Term Dict │ │ │
│ │ object_type │ │ Posting List │ │ │
│ │ display_name │ │ Doc Values │ │ │
│ │ description │ │ Norms │ │ │
│ │ properties │ └──────────────┘ │ │
│ └─────────────┴──────────────────┘ │
└──────────────────────────────────────┘
#2.2 Creating Inverted Indexes
Inverted index configuration for the Ontology object table in coomia-dip:
CREATE TABLE ontology_object_searchable (
tenant_id VARCHAR(64) NOT NULL COMMENT 'Tenant ID',
object_type VARCHAR(128) NOT NULL COMMENT 'Object type',
object_rid VARCHAR(256) NOT NULL COMMENT 'Object RID',
display_name VARCHAR(512) NOT NULL COMMENT 'Display name',
description TEXT COMMENT 'Description',
tags ARRAY<VARCHAR(64)> COMMENT 'Tag array',
properties_json TEXT COMMENT 'Properties JSON',
status VARCHAR(32) COMMENT 'Status',
created_at DATETIME COMMENT 'Created at',
updated_at DATETIME COMMENT 'Updated at',
-- Inverted index definitions
INDEX idx_display_name (display_name)
USING INVERTED
PROPERTIES("parser" = "unicode", "support_phrase" = "true"),
INDEX idx_description (description)
USING INVERTED
PROPERTIES(
"parser" = "unicode",
"support_phrase" = "true",
"lower_case" = "true"
),
INDEX idx_tags (tags)
USING INVERTED
PROPERTIES("parser" = "unicode"),
INDEX idx_properties (properties_json)
USING INVERTED
PROPERTIES("parser" = "unicode", "support_phrase" = "true"),
INDEX idx_status (status)
USING INVERTED,
INDEX idx_object_type (object_type)
USING INVERTED
)
UNIQUE KEY(tenant_id, object_type, object_rid)
DISTRIBUTED BY HASH(tenant_id) BUCKETS 16
PROPERTIES (
"replication_num" = "3",
"enable_unique_key_merge_on_write" = "true",
"inverted_index_storage_format" = "V2",
"store_row_column" = "true"
);
#2.3 Tokenizer Selection
| Tokenizer | Use Case | Configuration | Example |
|---|---|---|---|
unicode | Mixed CJK+English text | "parser" = "unicode" | "supply chain" → ["supply", "chain"] |
english | Pure English text | "parser" = "english" | "supply chain" → ["supply", "chain"] |
chinese | Pure Chinese text | "parser" = "chinese" | Uses jieba tokenization |
| None | Exact match | No parser specified | Suitable for enum values |
coomia-dip tokenizer strategy: Since the platform supports mixed Chinese-English scenarios, we use the unicode tokenizer uniformly. For fields requiring exact match (status, object_type), no tokenizer is configured for exact indexing.
#2.4 Full-Text Search Query Syntax
-- Basic full-text search: MATCH_ANY (OR semantics)
SELECT object_rid, display_name, description
FROM ontology_object_searchable
WHERE tenant_id = 'tenant-001'
AND display_name MATCH_ANY 'supply chain risk'
ORDER BY updated_at DESC
LIMIT 20;
-- Phrase search: MATCH_PHRASE (requires contiguous word order)
SELECT object_rid, display_name, description
FROM ontology_object_searchable
WHERE tenant_id = 'tenant-001'
AND description MATCH_PHRASE 'supply chain risk assessment'
LIMIT 20;
-- Full match search: MATCH_ALL (AND semantics)
SELECT object_rid, display_name, description
FROM ontology_object_searchable
WHERE tenant_id = 'tenant-001'
AND description MATCH_ALL 'supply chain risk assessment'
LIMIT 20;
-- Prefix search: MATCH_PHRASE_PREFIX
SELECT object_rid, display_name
FROM ontology_object_searchable
WHERE tenant_id = 'tenant-001'
AND display_name MATCH_PHRASE_PREFIX 'supply ch'
LIMIT 20;
-- Combined conditions: full-text search + exact filter
SELECT object_rid, display_name, description, status, created_at
FROM ontology_object_searchable
WHERE tenant_id = 'tenant-001'
AND description MATCH_ANY 'risk assessment alert'
AND status = 'ACTIVE'
AND created_at >= '2025-01-01'
ORDER BY created_at DESC
LIMIT 50;
#2.5 Inverted Index Performance Benchmarks
Benchmarks on coomia-dip test environment (3 BE nodes, 50 million records):
| Query Type | Without Inverted Index | With Inverted Index | Speedup |
|---|---|---|---|
| Exact match (status) | 1.2s | 0.03s | 40x |
| Keyword search (MATCH_ANY) | 5.6s | 0.18s | 31x |
| Phrase search (MATCH_PHRASE) | 8.3s | 0.25s | 33x |
| Fuzzy search (LIKE '%keyword%') | 12.1s | 0.30s | 40x |
| Combined query (text+filter+sort) | 15.2s | 0.42s | 36x |
#3. Vector Index Deep Analysis
#3.1 Vector Index Principle: HNSW
Doris uses the HNSW (Hierarchical Navigable Small World) algorithm for vector indexing:
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]
HNSW Key Parameters:
| Parameter | Meaning | Recommended | Performance Impact |
|---|---|---|---|
M | Max neighbors per layer | 16-64 | Higher = more accurate, more memory |
efConstruction | Search width during build | 200-500 | Higher = slower build, more accurate |
efSearch | Search width during query | 100-300 | Higher = slower query, more accurate |
#3.2 Creating Vector Index Tables
Semantic search table definition in coomia-dip:
CREATE TABLE ontology_embeddings (
tenant_id VARCHAR(64) NOT NULL COMMENT 'Tenant ID',
object_type VARCHAR(128) NOT NULL COMMENT 'Object type',
object_rid VARCHAR(256) NOT NULL COMMENT 'Object RID',
display_name VARCHAR(512) COMMENT 'Display name',
description TEXT COMMENT 'Description text',
embedding ARRAY<FLOAT> NOT NULL COMMENT 'Embedding vector (768-dim)',
model_version VARCHAR(32) COMMENT 'Model version',
created_at DATETIME COMMENT 'Created at',
-- Vector index
INDEX idx_embedding (embedding)
USING INVERTED
PROPERTIES(
"index_type" = "HNSW",
"metric_type" = "L2",
"dim" = "768",
"M" = "32",
"efConstruction" = "400"
),
-- Text inverted index (for hybrid queries)
INDEX idx_display_name (display_name)
USING INVERTED
PROPERTIES("parser" = "unicode"),
INDEX idx_description (description)
USING INVERTED
PROPERTIES("parser" = "unicode", "support_phrase" = "true")
)
UNIQUE KEY(tenant_id, object_type, object_rid)
DISTRIBUTED BY HASH(tenant_id) BUCKETS 16
PROPERTIES (
"replication_num" = "3",
"enable_unique_key_merge_on_write" = "true"
);
#3.3 Vector Data Import
Using the Python SDK to import embeddings into Doris:
# intelligence-Layer/embedding_indexer.py
import numpy as np
from typing import List, Dict
from sentence_transformers import SentenceTransformer
from doris_stream_loader import DorisStreamLoader
class OntologyEmbeddingIndexer:
"""Ontology object embedding indexer"""
def __init__(
self,
model_name: str = "BAAI/bge-base-zh-v1.5",
doris_host: str = "doris-fe-1",
doris_port: int = 8030
):
self.model = SentenceTransformer(model_name)
self.loader = DorisStreamLoader(doris_host, doris_port)
self.model_version = model_name.split("/")[-1]
def index_objects(
self,
tenant_id: str,
objects: List[Dict]
) -> int:
"""Batch index Ontology objects"""
records = []
texts = []
for obj in objects:
text = f"{obj['display_name']}. {obj.get('description', '')}"
texts.append(text)
# Batch encode
embeddings = self.model.encode(
texts,
batch_size=64,
show_progress_bar=True,
normalize_embeddings=True
)
for obj, embedding in zip(objects, embeddings):
records.append({
"tenant_id": tenant_id,
"object_type": obj["object_type"],
"object_rid": obj["object_rid"],
"display_name": obj["display_name"],
"description": obj.get("description", ""),
"embedding": embedding.tolist(),
"model_version": self.model_version,
"created_at": obj.get("created_at")
})
# Bulk import
result = self.loader.load_json_data(
database="ontology_db",
table="ontology_embeddings",
data=records
)
return len(records)
#3.4 Vector Search Queries
-- Basic vector similarity search (L2 distance)
SELECT
object_rid,
display_name,
L2_DISTANCE(embedding, ARRAY[0.1, 0.2, ...]) as distance
FROM ontology_embeddings
WHERE tenant_id = 'tenant-001'
ORDER BY distance ASC
LIMIT 10;
-- Cosine similarity search
SELECT
object_rid,
display_name,
COSINE_DISTANCE(embedding, ARRAY[0.1, 0.2, ...]) as distance
FROM ontology_embeddings
WHERE tenant_id = 'tenant-001'
ORDER BY distance ASC
LIMIT 10;
-- Inner product search
SELECT
object_rid,
display_name,
INNER_PRODUCT(embedding, ARRAY[0.1, 0.2, ...]) as score
FROM ontology_embeddings
WHERE tenant_id = 'tenant-001'
ORDER BY score DESC
LIMIT 10;
#3.5 Vector Index Performance Benchmarks
Vector search benchmarks on coomia-dip test environment (768-dimension vectors):
| Data Volume | Brute Force | HNSW (M=16) | HNSW (M=32) | HNSW (M=64) |
|---|---|---|---|---|
| 1M | 850ms | 12ms | 8ms | 6ms |
| 5M | 4.2s | 25ms | 15ms | 11ms |
| 10M | 8.5s | 45ms | 28ms | 18ms |
| 50M | 42s | 120ms | 75ms | 52ms |
Recall@100 Accuracy:
| Config | efSearch=100 | efSearch=200 | efSearch=400 |
|---|---|---|---|
| M=16 | 92.3% | 96.1% | 98.5% |
| M=32 | 95.7% | 98.2% | 99.3% |
| M=64 | 97.8% | 99.1% | 99.7% |
#4. Hybrid Query: OLAP + Vector + Full-Text
#4.1 Hybrid Query Architecture
One of coomia-dip's most powerful capabilities is combining OLAP analytics, vector search, and full-text search in a single query:
User query: "Find active objects created in the last 30 days
semantically similar to 'supply chain risk assessment'"
│
┌───────────┼───────────┐
▼ ▼ ▼
Vector Search Text Search OLAP Filter
(Semantic) (Keywords) (Time+Status)
│ │ │
└───────────┼───────────┘
▼
Result Fusion Ranking
(Weighted Scoring)
#4.2 Hybrid Query Implementation
-- Hybrid query: vector similarity + full-text match + OLAP filter
SELECT
e.object_rid,
e.display_name,
e.description,
e.object_type,
L2_DISTANCE(e.embedding, ARRAY[/* query embedding */]) as vector_distance,
e.created_at
FROM ontology_embeddings e
WHERE e.tenant_id = 'tenant-001'
-- OLAP filter
AND e.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
-- Full-text search
AND e.description MATCH_ANY 'supply chain risk'
ORDER BY vector_distance ASC
LIMIT 20;
#4.3 Advanced Hybrid Query: Weighted Scoring
-- Weighted hybrid scoring query
WITH vector_results AS (
SELECT
object_rid,
display_name,
description,
L2_DISTANCE(embedding, ARRAY[/* query embedding */]) as v_dist,
ROW_NUMBER() OVER (ORDER BY L2_DISTANCE(embedding, ARRAY[/* query embedding */])) as v_rank
FROM ontology_embeddings
WHERE tenant_id = 'tenant-001'
ORDER BY v_dist ASC
LIMIT 100
),
text_results AS (
SELECT
object_rid,
display_name,
description,
ROW_NUMBER() OVER (ORDER BY updated_at DESC) as t_rank
FROM ontology_object_searchable
WHERE tenant_id = 'tenant-001'
AND description MATCH_ANY 'supply chain risk assessment'
LIMIT 100
)
SELECT
COALESCE(v.object_rid, t.object_rid) as object_rid,
COALESCE(v.display_name, t.display_name) as display_name,
-- Weighted score: vector similarity weight 0.6, text match weight 0.4
(COALESCE(1.0 / v.v_rank, 0) * 0.6 +
COALESCE(1.0 / t.t_rank, 0) * 0.4) as hybrid_score
FROM vector_results v
FULL OUTER JOIN text_results t ON v.object_rid = t.object_rid
ORDER BY hybrid_score DESC
LIMIT 20;
#4.4 Search API Wrapper in coomia-dip
# intelligence-Layer/search/hybrid_search.py
from dataclasses import dataclass, field
from typing import List, Optional
from enum import Enum
class SearchMode(Enum):
KEYWORD = "keyword"
SEMANTIC = "semantic"
HYBRID = "hybrid"
@dataclass
class SearchRequest:
tenant_id: str
query: str
mode: SearchMode = SearchMode.HYBRID
object_types: Optional[List[str]] = None
status_filter: Optional[str] = None
date_from: Optional[str] = None
date_to: Optional[str] = None
top_k: int = 20
vector_weight: float = 0.6
text_weight: float = 0.4
@dataclass
class SearchResult:
object_rid: str
display_name: str
description: str
object_type: str
score: float
highlights: List[str] = field(default_factory=list)
class HybridSearchEngine:
"""Hybrid search engine — unified vector + full-text + OLAP"""
def __init__(self, doris_connection, embedding_model):
self.conn = doris_connection
self.model = embedding_model
async def search(self, request: SearchRequest) -> List[SearchResult]:
if request.mode == SearchMode.KEYWORD:
return await self._keyword_search(request)
elif request.mode == SearchMode.SEMANTIC:
return await self._semantic_search(request)
else:
return await self._hybrid_search(request)
async def _hybrid_search(self, request: SearchRequest) -> List[SearchResult]:
# 1. Generate query vector
query_embedding = self.model.encode(
request.query,
normalize_embeddings=True
)
# 2. Build hybrid query SQL
embedding_str = ", ".join(str(x) for x in query_embedding.tolist())
filters = [f"tenant_id = '{request.tenant_id}'"]
if request.object_types:
types_str = ", ".join(f"'{t}'" for t in request.object_types)
filters.append(f"object_type IN ({types_str})")
if request.status_filter:
filters.append(f"status = '{request.status_filter}'")
if request.date_from:
filters.append(f"created_at >= '{request.date_from}'")
where_clause = " AND ".join(filters)
sql = f"""
WITH vector_scores AS (
SELECT object_rid, display_name, description, object_type,
1.0 / (1.0 + L2_DISTANCE(embedding, ARRAY[{embedding_str}])) as v_score
FROM ontology_embeddings
WHERE {where_clause}
ORDER BY L2_DISTANCE(embedding, ARRAY[{embedding_str}]) ASC
LIMIT {request.top_k * 3}
),
text_scores AS (
SELECT object_rid, display_name, description, object_type,
1.0 as t_score
FROM ontology_object_searchable
WHERE {where_clause}
AND (display_name MATCH_ANY '{request.query}'
OR description MATCH_ANY '{request.query}')
LIMIT {request.top_k * 3}
)
SELECT
COALESCE(v.object_rid, t.object_rid) as object_rid,
COALESCE(v.display_name, t.display_name) as display_name,
COALESCE(v.description, t.description) as description,
COALESCE(v.object_type, t.object_type) as object_type,
(COALESCE(v.v_score, 0) * {request.vector_weight} +
COALESCE(t.t_score, 0) * {request.text_weight}) as score
FROM vector_scores v
FULL OUTER JOIN text_scores t ON v.object_rid = t.object_rid
ORDER BY score DESC
LIMIT {request.top_k}
"""
rows = await self.conn.execute(sql)
return [
SearchResult(
object_rid=row["object_rid"],
display_name=row["display_name"],
description=row["description"],
object_type=row["object_type"],
score=row["score"]
)
for row in rows
]
#5. Performance Comparison with Standalone Solutions
#5.1 Full-Text Search: Doris vs Elasticsearch
Comparison test on 50 million Ontology object records:
| Metric | Doris Inverted Index | Elasticsearch 8.x |
|---|---|---|
| Index build time | 45 min | 60 min |
| Storage space | 28 GB | 42 GB |
| Simple keyword search P50 | 35ms | 25ms |
| Simple keyword search P99 | 180ms | 120ms |
| Phrase search P50 | 65ms | 45ms |
| Phrase search P99 | 280ms | 200ms |
| Aggregation + search P50 | 120ms | 350ms (requires callback) |
| Aggregation + search P99 | 450ms | 1200ms |
| Concurrent 100 QPS latency | 250ms | 180ms |
| Data consistency delay | 0 (same source) | 1-5s (async sync) |
Conclusion: Elasticsearch has a slight advantage in pure search scenarios, but Doris significantly leads in search + analytics hybrid scenarios, with no data consistency issues.
#5.2 Vector Search: Doris vs Milvus
Comparison test on 10 million 768-dimension vectors:
| Metric | Doris HNSW | Milvus 2.4 (HNSW) |
|---|---|---|
| Index build time | 25 min | 18 min |
| Memory usage | 12 GB | 8 GB |
| Top-10 query P50 | 15ms | 8ms |
| Top-10 query P99 | 45ms | 25ms |
| Top-100 query P50 | 28ms | 15ms |
| Top-100 query P99 | 75ms | 42ms |
| Recall@100 | 98.2% | 98.5% |
| Filter + vector search P50 | 35ms | 65ms (pre/post filter) |
| Filter + vector search P99 | 95ms | 180ms |
| Vector + aggregation | Native support | Not supported |
Conclusion: Milvus is faster for pure vector search, but Doris performs better for filtered vector search and vector + analytics hybrid scenarios.
#6. Index Management and Operations
#6.1 Index Build Monitoring
-- Check index build progress
SHOW BUILD INDEX FROM ontology_db;
-- View table index information
SHOW INDEX FROM ontology_embeddings;
-- View segment-level index status
SHOW TABLET FROM ontology_embeddings;
#6.2 Index Rebuild
-- Drop and rebuild inverted index
DROP INDEX idx_description ON ontology_object_searchable;
CREATE INDEX idx_description ON ontology_object_searchable(description)
USING INVERTED
PROPERTIES("parser" = "unicode", "support_phrase" = "true");
-- Trigger index rebuild
BUILD INDEX idx_description ON ontology_object_searchable;
#6.3 Storage Space Optimization
-- Check index storage usage
SHOW DATA FROM ontology_embeddings;
-- Vector index compression (PQ quantization)
ALTER TABLE ontology_embeddings
MODIFY INDEX idx_embedding
PROPERTIES("index_type" = "HNSW", "pq_enable" = "true", "pq_subvector_num" = "48");
#7. Production Configuration Checklist
#7.1 Vector Search Optimization
# be.conf — vector search related
enable_vectorized_engine = true
inverted_index_ram_dir_enable = true # Cache index in memory
# Vector index search threads
vector_index_search_thread_pool_size = 16
# HNSW search parameters (global defaults)
default_hnsw_ef_search = 200
#7.2 Inverted Index Optimization
# be.conf — inverted index related
inverted_index_cache_stale_sweep_time_sec = 600
inverted_index_max_buffered_docs = 65536
inverted_index_compaction_enable = true
# Tokenizer cache
inverted_index_searcher_cache_limit = 10%
#7.3 Memory Allocation Recommendations
For BE nodes simultaneously using OLAP analytics, inverted indexes, and vector indexes:
Total 64GB allocation plan:
├── Query execution engine 30GB (47%)
├── Vector index cache 10GB (16%)
├── Inverted index cache 8GB (12%)
├── Page cache 8GB (12%)
├── Compaction 5GB (8%)
└── System reserved 3GB (5%)
#8. Common Issues and Solutions
#8.1 Vector Dimension Mismatch
Problem: Different models generate embeddings with different dimensions; mixing causes query failures.
Solution:
-- Use model_version field to isolate vectors from different models
SELECT * FROM ontology_embeddings
WHERE tenant_id = 'tenant-001'
AND model_version = 'bge-base-zh-v1.5'
ORDER BY L2_DISTANCE(embedding, ARRAY[...]) ASC
LIMIT 10;
#8.2 Inverted Index Space Bloat
Problem: Inverted indexes on TEXT fields consume excessive storage.
Solution:
-- Limit indexed tokens per document for long text fields
ALTER TABLE ontology_object_searchable
MODIFY INDEX idx_description
PROPERTIES("max_token_per_doc" = "10000");
#8.3 Unstable Hybrid Query Performance
Problem: Large vector search result sets slow down subsequent OLAP computation.
Solution:
-- Strategy 1: Filter with scalar predicates first, then vector search
-- Strategy 2: Use partition key + vector index for partition pruning
-- Strategy 3: Two-phase query — coarse screening then fine ranking
#9. Evolution Roadmap
coomia-dip Doris vector + full-text capability evolution plan:
| Phase | Timeline | Goal |
|---|---|---|
| V1 (Current) | 2025 Q1 | Basic inverted index + HNSW vector index |
| V2 | 2025 Q2 | Hybrid search score fusion + BM25 scoring |
| V3 | 2025 Q3 | Multi-modal vectors (text + image) |
| V4 | 2025 Q4 | Adaptive index selection + AutoML scoring |
#Key Takeaways
-
Unified engine is the greatest value: Doris's inverted and vector indexes allow coomia-dip to avoid the additional complexity of maintaining Elasticsearch + Milvus. While individual performance is not the absolute best, the data consistency and operational simplification from a unified engine far outweigh the performance gap.
-
Hybrid query is the core differentiator: The ability to combine OLAP filtering + full-text search + vector search in a single SQL statement is coomia-dip's core competitive advantage over traditional analytics platforms. Palantir Foundry requires multiple service coordination to achieve similar functionality.
-
Tokenizer and index parameters need scenario-specific tuning: The unicode tokenizer suits mixed CJK+English content; HNSW with M=32 + efSearch=200 is the optimal balance between accuracy and performance. In production, ensure sufficient memory is reserved for index caching.
#Next Article Preview
S8-03: Apache Nessie Deep Dive: Git-Like Data Version Control — Exploring how Nessie enables data branching, merging, and time travel, and how coomia-dip's Lakehouse architecture manages Ontology data version evolution.
Tags: #apache-doris #vector-index #inverted-index #hnsw #full-text-search #hybrid-search #coomia-dip #Layer-c