Apache Doris 统一 OLAP、向量搜索和全文检索的实践
Tags: #Doris #OLAP #VectorSearch #HNSW #InvertedIndex #FullTextSearch #智策平台
“系列:S3 数据基座 · 第 1 篇 | 难度:高级 | 阅读时间:20 分钟
Apache Doris 统一 OLAP、向量搜索和全文检索的实践
Tags: #Doris #OLAP #VectorSearch #HNSW #InvertedIndex #FullTextSearch #智策平台
#TL;DR
在智策平台(coomia-dip)中,我们选择 Apache Doris 作为核心分析引擎,同时承担 OLAP 聚合分析、向量相似度搜索(HNSW 索引)和全文检索(倒排索引)三大职责。本文详细剖析为何不再需要 ClickHouse + Qdrant + Elasticsearch 的组合架构,以及如何在一条查询中同时完成聚合计算、语义搜索和关键词匹配。通过实际基准测试数据和生产配置,展示 Doris 统一引擎在性能、运维复杂度和开发效率上的全面优势。
#1. 为什么选择统一引擎
#1.1 多引擎架构的痛点
传统的数据平台在面对多种查询需求时,往往采用"专用引擎"策略:
传统多引擎架构:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ ClickHouse │ │ Qdrant │ │Elasticsearch│
│ (OLAP) │ │ (Vector) │ │ (Full-Text) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────┬───────┴────────────────┘
│
┌───────┴───────┐
│ Application │
│ Query Router │
└───────────────┘
这种架构带来三个核心问题:
| 问题 | 影响 | 量化成本 |
|---|---|---|
| 数据同步 | 同一份数据需要写入三个系统,一致性保证困难 | 开发周期 +40% |
| 运维负担 | 三套集群的部署、监控、升级、扩容 | 运维人力 ×3 |
| 跨引擎查询 | 需要在应用层做结果合并和二次排序 | 查询延迟 +200ms~2s |
| 资源浪费 | 热数据在三个系统中重复存储 | 存储成本 ×2.5 |
#1.2 Doris 的统一能力矩阵
Apache Doris 从 2.0 版本开始,逐步引入了向量索引和倒排索引能力,使得单一引擎覆盖三大场景成为可能:
统一引擎架构(coomia-dip 采用):
┌──────────────────────┐
│ Apache Doris │
│ ┌────┬─────┬─────┐ │
│ │OLAP│HNSW │Inv. │ │
│ │Agg │Vec │Index│ │
│ └────┴─────┴─────┘ │
└──────────┬───────────┘
│
┌───────┴───────┐
│ Application │
│ (Single API) │
└───────────────┘
关键能力对比:
| 能力 | ClickHouse | Doris 2.1+ | 差距 |
|---|---|---|---|
| 列式存储 OLAP | 优秀 | 优秀 | 持平 |
| 物化视图 | 部分支持 | 同步/异步均支持 | Doris 更强 |
| 向量搜索(HNSW) | 不支持 | 原生支持 | Doris 独有 |
| 倒排索引 | 不支持 | 原生支持 | Doris 独有 |
| MySQL 协议兼容 | 不兼容 | 完全兼容 | Doris 更友好 |
| Join 性能 | 一般 | Shuffle Join + Colocation | Doris 更优 |
#1.3 决策矩阵
我们使用加权评分法做出最终决策:
| 评估维度 | 权重 | 多引擎方案 | Doris 统一方案 |
|---|---|---|---|
| 查询性能 | 30% | 9(各自最优) | 8(轻微妥协) |
| 运维成本 | 25% | 3(三套系统) | 9(单一系统) |
| 数据一致性 | 20% | 4(跨系统同步) | 10(单一数据源) |
| 开发效率 | 15% | 4(多 SDK 集成) | 9(统一 SQL) |
| 资源利用率 | 10% | 4(重复存储) | 9(共享存储) |
| 加权总分 | — | 5.35 | 8.85 |
#2. Doris OLAP 核心能力
#2.1 列式存储引擎
Doris 采用 MPP(Massively Parallel Processing)架构,数据以列式存储在多个 BE(Backend)节点上:
Doris 集群架构:
┌─────────┐
│ FE │ Frontend: SQL 解析、查询规划、元数据管理
│ (Leader)│
└────┬────┘
│
┌─────┼─────────────────────────────┐
│ │ BE Cluster │
│ ┌──┴──┐ ┌─────┐ ┌─────┐ │
│ │ BE1 │ │ BE2 │ │ BE3 │ │
│ │ │ │ │ │ │ │
│ │Tab1 │ │Tab1 │ │Tab1 │ │
│ │Part │ │Part │ │Part │ │
│ │ 1,4 │ │ 2,5 │ │ 3,6 │ │
│ └─────┘ └─────┘ └─────┘ │
└──────────────────────────────────┘
#2.2 coomia-dip 中的表设计
以 entity_common 表为例(详见 S3-05),我们在 Doris 中的建表语句:
CREATE TABLE IF NOT EXISTS entity_common (
-- 分区键
world_id VARCHAR(64) NOT NULL COMMENT '世界ID',
object_type_id VARCHAR(128) NOT NULL COMMENT '对象类型ID',
entity_id VARCHAR(128) NOT NULL COMMENT '实体ID',
-- 核心属性(高频查询列)
title VARCHAR(512) NULL COMMENT '标题',
status VARCHAR(32) NULL COMMENT '状态',
created_at DATETIME NOT NULL COMMENT '创建时间',
updated_at DATETIME NOT NULL COMMENT '更新时间',
-- 灵活属性(JSON 列)
properties JSON NULL COMMENT '动态属性 JSON',
-- 向量列(嵌入)
embedding ARRAY<FLOAT> NULL COMMENT '语义嵌入向量 (768维)',
-- 全文检索列
search_text TEXT NULL COMMENT '全文检索文本'
)
ENGINE = OLAP
DUPLICATE KEY(world_id, object_type_id, entity_id)
PARTITION BY RANGE(created_at) (
PARTITION p202601 VALUES LESS THAN ('2026-02-01'),
PARTITION p202602 VALUES LESS THAN ('2026-03-01'),
PARTITION p202603 VALUES LESS THAN ('2026-04-01')
)
DISTRIBUTED BY HASH(entity_id) BUCKETS 16
PROPERTIES (
"replication_allocation" = "tag.location.default: 3",
"storage_format" = "V2",
"enable_unique_key_merge_on_write" = "true"
);
#2.3 OLAP 聚合查询示例
-- 按类型统计实体数量,按月分组
SELECT
object_type_id,
DATE_TRUNC('month', created_at) AS month,
COUNT(*) AS entity_count,
COUNT(DISTINCT status) AS status_variety,
AVG(JSON_EXTRACT_DOUBLE(properties, '$.risk_score')) AS avg_risk
FROM entity_common
WHERE world_id = 'world-prod-001'
AND created_at >= '2026-01-01'
GROUP BY object_type_id, DATE_TRUNC('month', created_at)
ORDER BY month DESC, entity_count DESC
LIMIT 100;
Doris 在 OLAP 场景下的优势在于其向量化执行引擎和列式存储的完美结合。对于上述查询,Doris 会:
- 分区裁剪:根据
created_at条件只扫描相关分区 - 谓词下推:
world_id过滤在存储层完成 - 向量化计算:COUNT、AVG 等聚合使用 SIMD 指令
- 并行执行:各 BE 节点并行处理各自的 Bucket
#3. HNSW 向量索引:语义搜索
#3.1 向量搜索原理
HNSW(Hierarchical Navigable Small World)是一种基于图的近似最近邻(ANN)搜索算法。其核心思想是构建多层跳表式图结构:
HNSW 多层图结构:
Layer 2: [A]─────────────────[D]
│ │
Layer 1: [A]────[B]────[C]───[D]────[E]
│ │ │ │ │
Layer 0: [A]─[F]─[B]─[G]─[C]─[H]─[D]─[I]─[E]─[J]
搜索过程(查找最近邻 of Q):
1. 从 Layer 2 的入口点 A 开始
2. 在 Layer 2 贪婪搜索: A → D(D 更接近 Q)
3. 下降到 Layer 1: D → E(E 更接近 Q)
4. 下降到 Layer 0: E → I → J(找到最近邻)
#3.2 在 Doris 中创建 HNSW 索引
-- 为 entity_common 表的 embedding 列创建 HNSW 索引
ALTER TABLE entity_common
ADD INDEX idx_embedding_hnsw (embedding)
USING INVERTED
PROPERTIES (
"index_type" = "HNSW",
"metric_type" = "COSINE",
"dim" = "768",
"M" = "32",
"ef_construction" = "200"
);
HNSW 参数解释:
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
M | 16 | 32 | 每个节点的最大连接数。越大召回率越高,索引越大 |
ef_construction | 100 | 200 | 构建时的搜索宽度。越大索引质量越高,构建越慢 |
ef_search | 100 | 150 | 查询时的搜索宽度。越大召回率越高,查询越慢 |
metric_type | L2 | COSINE | 距离度量。语义搜索推荐 COSINE |
dim | - | 768 | 向量维度。须与嵌入模型输出维度一致 |
#3.3 向量搜索查询
-- 语义搜索:查找与给定向量最相似的 10 个实体
SELECT
entity_id,
title,
object_type_id,
COSINE_DISTANCE(embedding, ARRAY[0.12, -0.34, ..., 0.56]) AS distance
FROM entity_common
WHERE world_id = 'world-prod-001'
AND object_type_id = 'Equipment'
ORDER BY distance ASC
LIMIT 10;
#3.4 向量搜索 + OLAP 过滤联合查询
这是 Doris 统一引擎的核心优势——在一条 SQL 中同时完成标量过滤和向量搜索:
-- 联合查询:在特定条件下进行语义搜索
SELECT
entity_id,
title,
status,
JSON_EXTRACT_STRING(properties, '$.department') AS department,
COSINE_DISTANCE(embedding, ARRAY[0.12, -0.34, ..., 0.56]) AS similarity
FROM entity_common
WHERE world_id = 'world-prod-001'
AND object_type_id = 'Employee'
AND status = 'active'
AND created_at >= '2026-01-01'
ORDER BY similarity ASC
LIMIT 20;
执行过程分析:
查询执行计划:
┌────────────────────────┐
│ Result (Top 20) │
└────────┬───────────────┘
│
┌────────┴───────────────┐
│ Sort by similarity │
│ (TopN Heap Sort) │
└────────┬───────────────┘
│
┌────────┴───────────────┐
│ HNSW Vector Search │
│ (ANN on embedding) │
└────────┬───────────────┘
│
┌────────┴───────────────┐
│ Predicate Filter │
│ world_id = '...' │
│ object_type_id = '...'│
│ status = 'active' │
│ created_at >= '...' │
└────────┬───────────────┘
│
┌────────┴───────────────┐
│ Partition Pruning │
│ (created_at range) │
└────────────────────────┘
#4. 倒排索引:全文检索
#4.1 Doris 倒排索引架构
Doris 2.0 引入了基于 CLucene 的倒排索引,支持全文检索、短语匹配和分词:
倒排索引内部结构:
Document: "Apache Doris is a high-performance analytics database"
Tokenization (分词):
┌────────┬──────────────────────────┐
│ Token │ Posting List (文档ID列表) │
├────────┼──────────────────────────┤
│ apache │ [1, 15, 42, 88] │
│ doris │ [1, 3, 15, 42] │
│ high │ [1, 7, 23, 56, 88] │
│ perf* │ [1, 7, 12, 56] │
│ analyt*│ [1, 3, 42, 67] │
│ datab* │ [1, 3, 7, 42, 67, 88] │
└────────┴──────────────────────────┘
#4.2 创建倒排索引
-- 为 search_text 列创建倒排索引(支持中文分词)
ALTER TABLE entity_common
ADD INDEX idx_search_text (search_text)
USING INVERTED
PROPERTIES (
"parser" = "unicode",
"support_phrase" = "true",
"lower_case" = "true"
);
-- 为 title 列创建倒排索引
ALTER TABLE entity_common
ADD INDEX idx_title_inv (title)
USING INVERTED
PROPERTIES (
"parser" = "unicode",
"support_phrase" = "true"
);
#4.3 全文检索查询
-- 全文检索:搜索包含"风险评估"的实体
SELECT
entity_id,
title,
object_type_id,
search_text
FROM entity_common
WHERE world_id = 'world-prod-001'
AND MATCH_ALL(search_text, '风险评估')
ORDER BY updated_at DESC
LIMIT 20;
-- 短语匹配
SELECT entity_id, title
FROM entity_common
WHERE MATCH_PHRASE(search_text, '数据质量检查')
LIMIT 10;
-- 模糊匹配
SELECT entity_id, title
FROM entity_common
WHERE MATCH_ALL(title, '设备故障')
AND object_type_id = 'MaintenanceRecord'
LIMIT 10;
#4.4 中文分词配置
-- 使用 unicode 分词器处理中英文混合文本
-- Doris 内置 unicode 分词器支持 CJK(中日韩)字符
-- 验证分词效果
SELECT TOKENIZE('设备故障报告-2026年第一季度', 'unicode');
-- 结果: ["设备", "故障", "报告", "2026", "年", "第一", "季度"]
#5. 三合一查询:OLAP + 向量 + 全文
#5.1 终极联合查询
这是 Doris 统一引擎的巅峰体验——一条查询同时利用三种能力:
-- 场景:在活跃的设备中,搜索与"异常振动"语义相关的记录,
-- 同时包含"维修"关键词,并按部门聚合统计
WITH semantic_matches AS (
SELECT
entity_id,
title,
status,
JSON_EXTRACT_STRING(properties, '$.department') AS department,
JSON_EXTRACT_DOUBLE(properties, '$.severity') AS severity,
COSINE_DISTANCE(embedding, ARRAY[0.12, -0.34, ..., 0.56]) AS vec_distance
FROM entity_common
WHERE world_id = 'world-prod-001'
AND object_type_id = 'MaintenanceRecord'
AND status IN ('open', 'in_progress')
AND MATCH_ALL(search_text, '维修')
ORDER BY vec_distance ASC
LIMIT 200
)
SELECT
department,
COUNT(*) AS record_count,
AVG(severity) AS avg_severity,
MIN(vec_distance) AS best_semantic_match,
GROUP_CONCAT(title ORDER BY vec_distance ASC SEPARATOR ' | ') AS top_titles
FROM semantic_matches
GROUP BY department
ORDER BY avg_severity DESC;
查询执行流程:
三合一查询执行流程:
Step 1: Partition Pruning (分区裁剪)
└─ created_at range → scan only relevant partitions
Step 2: Predicate Push-down (谓词下推)
├─ world_id = 'world-prod-001' → Prefix Index
├─ object_type_id = 'Maintenance...' → Prefix Index
└─ status IN ('open', 'in_progress') → Bitmap Index
Step 3: Inverted Index Scan (倒排索引)
└─ MATCH_ALL(search_text, '维修') → Posting List
Step 4: HNSW Vector Search (向量搜索)
└─ COSINE_DISTANCE(embedding, [...]) → ANN Top-200
Step 5: Intersection (交集)
└─ Step2 ∩ Step3 ∩ Step4
Step 6: Aggregation (聚合)
└─ GROUP BY department + AVG + COUNT
#5.2 查询性能对比
我们使用 1000 万条 entity_common 记录进行基准测试:
| 查询类型 | 多引擎方案 | Doris 统一方案 | 提升 |
|---|---|---|---|
| 纯 OLAP 聚合 | 180ms (CH) | 210ms | -14% |
| 纯向量搜索 Top-10 | 12ms (Qdrant) | 25ms | -52% |
| 纯全文检索 | 35ms (ES) | 45ms | -22% |
| OLAP + 向量联合 | 380ms (跨系统) | 85ms | +77% |
| OLAP + 全文联合 | 290ms (跨系统) | 65ms | +78% |
| 三合一联合 | 650ms (跨系统) | 120ms | +82% |
| 数据写入延迟 | 3 份写入 150ms | 1 份写入 50ms | +67% |
关键发现: 虽然 Doris 在单一场景下略逊于专用引擎(10-50%),但在联合查询场景下性能大幅超越多引擎方案(70-80%),因为消除了跨系统网络延迟和结果合并开销。
#6. 配置与调优
#6.1 FE 配置
# fe.conf - 智策平台推荐配置
# 内存配置
JAVA_OPTS="-Xmx8g -Xms4g"
# 查询超时
max_query_timeout = 300
# 向量搜索参数
default_hnsw_ef_search = 150
# 倒排索引配置
inverted_index_ram_dir_enable = true
# 并发控制
max_running_txn_num_per_db = 1000
qe_max_connection = 2048
#6.2 BE 配置
# be.conf - 智策平台推荐配置
# 内存配置
mem_limit = 80%
storage_page_cache_limit = 40%
# 向量搜索内存
vector_index_cache_capacity = 2147483648 # 2GB
# 压缩
default_rowset_type = BETA
compaction_task_num_per_disk = 4
# 并发
doris_scanner_thread_pool_thread_num = 48
doris_scanner_thread_pool_queue_size = 102400
# 存储
storage_root_path = /data/doris/storage
#6.3 索引调优指南
索引选择决策树:
┌─────────────────┐
│ 查询类型是什么? │
└────────┬────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ 精确匹配 │ │ 语义搜索 │ │ 全文检索 │
│ 范围查询 │ │ 相似度 │ │ 关键词 │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ Prefix/ │ │ HNSW │ │ Inverted │
│ Bitmap │ │ Index │ │ Index │
│ Index │ │ │ │ │
└───────────┘ └───────────┘ └───────────┘
#6.4 分区与分桶策略
-- 动态分区配置(自动管理月分区)
ALTER TABLE entity_common SET (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "MONTH",
"dynamic_partition.start" = "-12",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "16",
"dynamic_partition.replication_allocation" = "tag.location.default: 3"
);
#7. coomia-dip 集成架构
#7.1 数据写入流程
数据写入流程:
┌──────────┐ ┌─────────────┐ ┌──────────────┐
│ Control │gRPC │ Data Layer │ │ Doris │
│ Layer ├────>│ WriteService├────>│ (Stream │
│ (B) │ │ │ │ Load) │
└──────────┘ └──────┬──────┘ └──────────────┘
│
│ async
v
┌──────────────┐
│ Embedding │
│ Service (D) │
│ (生成向量) │
└──────┬───────┘
│
v
┌──────────────┐
│ Doris UPDATE │
│ (embedding │
│ column) │
└──────────────┘
#7.2 查询服务架构
# python-sdk 中的 Doris 查询客户端
class DorisQueryClient:
"""统一查询客户端,支持 OLAP/向量/全文三合一查询"""
def __init__(self, config: DorisConfig):
self.pool = ConnectionPool(
host=config.host,
port=config.query_port,
user=config.user,
password=config.password,
database=config.database,
pool_size=config.pool_size
)
async def unified_search(
self,
world_id: str,
object_type_id: str,
*,
filters: dict | None = None,
vector_query: list[float] | None = None,
text_query: str | None = None,
aggregations: list[str] | None = None,
limit: int = 100
) -> QueryResult:
"""三合一统一搜索"""
sql_builder = UnifiedSQLBuilder()
# 基础条件
sql_builder.add_condition("world_id", "=", world_id)
sql_builder.add_condition("object_type_id", "=", object_type_id)
# 标量过滤
if filters:
for key, value in filters.items():
sql_builder.add_condition(key, "=", value)
# 向量搜索
if vector_query:
sql_builder.add_vector_search("embedding", vector_query, metric="cosine")
# 全文检索
if text_query:
sql_builder.add_text_search("search_text", text_query)
# 聚合
if aggregations:
for agg in aggregations:
sql_builder.add_aggregation(agg)
sql = sql_builder.build(limit=limit)
return await self.execute(sql)
#7.3 gRPC 服务定义
// query_service.proto
service UnifiedQueryService {
// 统一查询接口
rpc ExecuteQuery(QueryRequest) returns (QueryResponse);
// 向量搜索
rpc VectorSearch(VectorSearchRequest) returns (SearchResponse);
// 全文检索
rpc TextSearch(TextSearchRequest) returns (SearchResponse);
// 混合查询
rpc HybridSearch(HybridSearchRequest) returns (SearchResponse);
}
message HybridSearchRequest {
string world_id = 1;
string object_type_id = 2;
repeated Filter filters = 3;
VectorQuery vector_query = 4;
TextQuery text_query = 5;
repeated Aggregation aggregations = 6;
int32 limit = 7;
}
#8. 生产环境基准测试
#8.1 测试环境
| 配置项 | 值 |
|---|---|
| 集群规模 | 3 FE + 5 BE |
| BE 配置 | 32C / 128GB / 2TB NVMe SSD |
| 数据量 | 5000 万条 entity_common 记录 |
| 向量维度 | 768 (BGE-large-zh) |
| 索引 | HNSW(M=32, ef=200) + 倒排索引 |
#8.2 测试结果
查询延迟分布 (P50 / P95 / P99):
OLAP 聚合查询(10 列 GROUP BY):
P50: 120ms P95: 350ms P99: 800ms
████████████▒▒▒░░░░░░░░░░░░░░░░░░
向量搜索 Top-100:
P50: 18ms P95: 45ms P99: 90ms
███▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░
全文检索(中文分词):
P50: 25ms P95: 80ms P99: 150ms
█████▒▒░░░░░░░░░░░░░░░░░░░░░░░░░
三合一联合查询:
P50: 85ms P95: 250ms P99: 500ms
█████████▒▒▒░░░░░░░░░░░░░░░░░░░░
写入吞吐(Stream Load):
单 BE: 50,000 rows/sec
集群: 200,000 rows/sec
#8.3 资源使用
集群资源使用情况(5 BE 节点平均):
CPU: ██████████████░░░░░░ 68%
Memory: ████████████████░░░░ 82%
Disk IO: ██████████░░░░░░░░░░ 48%
Network: ████░░░░░░░░░░░░░░░░ 22%
#9. 常见问题与解决方案
#9.1 向量索引构建慢
问题: 大表添加 HNSW 索引时,构建时间过长。
解决方案:
-- 1. 调整构建参数(降低 ef_construction)
ALTER TABLE entity_common
ADD INDEX idx_emb_hnsw (embedding) USING INVERTED
PROPERTIES ("index_type"="HNSW", "M"="16", "ef_construction"="100");
-- 2. 分批构建(先建空表带索引,再导入数据)
-- 3. 使用 Routine Load 增量构建
#9.2 向量召回率不够
问题: HNSW 近似搜索丢失部分相关结果。
解决方案:
-- 增加 ef_search 参数(牺牲速度换召回率)
SET SESSION hnsw_ef_search = 300;
-- 增加候选集大小
SELECT entity_id, COSINE_DISTANCE(embedding, ...) AS dist
FROM entity_common
WHERE ...
ORDER BY dist ASC
LIMIT 50; -- 多取一些再在应用层精排
#9.3 中文分词效果不佳
问题: 默认分词器对专业术语处理不好。
解决方案:
-- 使用自定义词典
-- 在 BE 节点 conf/dict/ 目录下添加自定义词典文件
-- custom_dict.txt:
-- 智策平台
-- 本体驱动
-- 数据基座
-- 重建索引使其生效
ALTER TABLE entity_common DROP INDEX idx_search_text;
ALTER TABLE entity_common ADD INDEX idx_search_text (search_text)
USING INVERTED PROPERTIES (
"parser" = "unicode",
"support_phrase" = "true",
"dict_path" = "custom_dict.txt"
);
#10. 与 coomia-dip 其他组件的关系
coomia-dip 存储层全景:
┌─────────────────────────────────────────────────┐
│ Query Layer │
│ ┌──────────────────────────────────────────┐ │
│ │ QueryFederationService (C) │ │
│ └──────┬──────────────────┬────────────────┘ │
│ │ │ │
│ ┌────┴─────┐ ┌────┴─────┐ │
│ │ Doris │ │ DuckDB │ │
│ │ (主引擎) │ │ (辅引擎) │ │
│ └────┬─────┘ └──────────┘ │
│ │ │
│ ┌────┴──────────────────────────────┐ │
│ │ Storage Layer │ │
│ │ ┌─────────┐ ┌────────────────┐ │ │
│ │ │ MinIO │ │ Nessie+Iceberg │ │ │
│ │ │ (对象) │ │ (版本化湖仓) │ │ │
│ │ └─────────┘ └────────────────┘ │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
#Key Takeaways
-
统一引擎 > 专用引擎组合:在多模查询场景下,Doris 统一方案的联合查询性能比多引擎方案快 70-82%,同时大幅降低运维复杂度。
-
HNSW 索引让 OLAP 引擎具备语义搜索能力:通过合理配置 M 和 ef 参数,可以在召回率和性能之间找到最佳平衡点。
-
倒排索引支持中文全文检索:Doris 内置的 unicode 分词器加上自定义词典,可以满足中文场景下的全文检索需求。
-
三合一查询是杀手级特性:在一条 SQL 中同时完成 OLAP 聚合 + 向量搜索 + 全文检索,这是任何多引擎方案都无法高效实现的。
-
合理的索引策略是性能关键:根据查询模式选择合适的索引类型(Prefix/Bitmap/HNSW/Inverted),并通过分区和分桶策略优化数据分布。
#Next Article
下一篇 S3-02《像 Git 一样管理数据:Nessie + Iceberg 实现数据版本控制》 将深入探讨如何使用 Nessie 和 Iceberg 为智策平台的数据层提供 Git 风格的版本控制能力,包括分支、合并、冲突解决和时间旅行查询。
Tags: #ApacheDoris #OLAP #VectorSearch #HNSW #InvertedIndex #FullTextSearch #智策平台 #coomia-dip #统一引擎 #数据基座