返回博客

Apache Doris 统一 OLAP、向量搜索和全文检索的实践

Tags: #Doris #OLAP #VectorSearch #HNSW #InvertedIndex #FullTextSearch #智策平台

Coomia发布于 2025年7月10日19 分钟阅读
分享本文Twitter / X

系列: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 多引擎架构的痛点

传统的数据平台在面对多种查询需求时,往往采用"专用引擎"策略:

Code
传统多引擎架构:

┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│ ClickHouse  │  │   Qdrant    │  │Elasticsearch│
│  (OLAP)     │  │  (Vector)   │  │ (Full-Text) │
└──────┬──────┘  └──────┬──────┘  └──────┬──────┘
       │                │                │
       └────────┬───────┴────────────────┘
                │
        ┌───────┴───────┐
        │  Application  │
        │  Query Router │
        └───────────────┘

这种架构带来三个核心问题:

问题影响量化成本
数据同步同一份数据需要写入三个系统,一致性保证困难开发周期 +40%
运维负担三套集群的部署、监控、升级、扩容运维人力 ×3
跨引擎查询需要在应用层做结果合并和二次排序查询延迟 +200ms~2s
资源浪费热数据在三个系统中重复存储存储成本 ×2.5

#1.2 Doris 的统一能力矩阵

Apache Doris 从 2.0 版本开始,逐步引入了向量索引和倒排索引能力,使得单一引擎覆盖三大场景成为可能:

Code
统一引擎架构(coomia-dip 采用):

                ┌──────────────────────┐
                │    Apache Doris      │
                │  ┌────┬─────┬─────┐  │
                │  │OLAP│HNSW │Inv. │  │
                │  │Agg │Vec  │Index│  │
                │  └────┴─────┴─────┘  │
                └──────────┬───────────┘
                           │
                   ┌───────┴───────┐
                   │  Application  │
                   │ (Single API)  │
                   └───────────────┘

关键能力对比:

能力ClickHouseDoris 2.1+差距
列式存储 OLAP优秀优秀持平
物化视图部分支持同步/异步均支持Doris 更强
向量搜索(HNSW)不支持原生支持Doris 独有
倒排索引不支持原生支持Doris 独有
MySQL 协议兼容不兼容完全兼容Doris 更友好
Join 性能一般Shuffle Join + ColocationDoris 更优

#1.3 决策矩阵

我们使用加权评分法做出最终决策:

评估维度权重多引擎方案Doris 统一方案
查询性能30%9(各自最优)8(轻微妥协)
运维成本25%3(三套系统)9(单一系统)
数据一致性20%4(跨系统同步)10(单一数据源)
开发效率15%4(多 SDK 集成)9(统一 SQL)
资源利用率10%4(重复存储)9(共享存储)
加权总分5.358.85

#2. Doris OLAP 核心能力

#2.1 列式存储引擎

Doris 采用 MPP(Massively Parallel Processing)架构,数据以列式存储在多个 BE(Backend)节点上:

Code
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 中的建表语句:

SQL
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 聚合查询示例

SQL
-- 按类型统计实体数量,按月分组
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 会:

  1. 分区裁剪:根据 created_at 条件只扫描相关分区
  2. 谓词下推world_id 过滤在存储层完成
  3. 向量化计算:COUNT、AVG 等聚合使用 SIMD 指令
  4. 并行执行:各 BE 节点并行处理各自的 Bucket

#3. HNSW 向量索引:语义搜索

#3.1 向量搜索原理

HNSW(Hierarchical Navigable Small World)是一种基于图的近似最近邻(ANN)搜索算法。其核心思想是构建多层跳表式图结构:

Code
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 索引

SQL
-- 为 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 参数解释:

参数默认值推荐值说明
M1632每个节点的最大连接数。越大召回率越高,索引越大
ef_construction100200构建时的搜索宽度。越大索引质量越高,构建越慢
ef_search100150查询时的搜索宽度。越大召回率越高,查询越慢
metric_typeL2COSINE距离度量。语义搜索推荐 COSINE
dim-768向量维度。须与嵌入模型输出维度一致

#3.3 向量搜索查询

SQL
-- 语义搜索:查找与给定向量最相似的 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 中同时完成标量过滤和向量搜索:

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;

执行过程分析:

Code
查询执行计划:

┌────────────────────────┐
│    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 的倒排索引,支持全文检索、短语匹配和分词:

Code
倒排索引内部结构:

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 创建倒排索引

SQL
-- 为 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 全文检索查询

SQL
-- 全文检索:搜索包含"风险评估"的实体
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 中文分词配置

SQL
-- 使用 unicode 分词器处理中英文混合文本
-- Doris 内置 unicode 分词器支持 CJK(中日韩)字符

-- 验证分词效果
SELECT TOKENIZE('设备故障报告-2026年第一季度', 'unicode');
-- 结果: ["设备", "故障", "报告", "2026", "年", "第一", "季度"]

#5. 三合一查询:OLAP + 向量 + 全文

#5.1 终极联合查询

这是 Doris 统一引擎的巅峰体验——一条查询同时利用三种能力:

SQL
-- 场景:在活跃的设备中,搜索与"异常振动"语义相关的记录,
-- 同时包含"维修"关键词,并按部门聚合统计

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;

查询执行流程:

Code
三合一查询执行流程:

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-1012ms (Qdrant)25ms-52%
纯全文检索35ms (ES)45ms-22%
OLAP + 向量联合380ms (跨系统)85ms+77%
OLAP + 全文联合290ms (跨系统)65ms+78%
三合一联合650ms (跨系统)120ms+82%
数据写入延迟3 份写入 150ms1 份写入 50ms+67%

关键发现: 虽然 Doris 在单一场景下略逊于专用引擎(10-50%),但在联合查询场景下性能大幅超越多引擎方案(70-80%),因为消除了跨系统网络延迟和结果合并开销。

#6. 配置与调优

#6.1 FE 配置

PROPERTIES
# 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 配置

PROPERTIES
# 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 索引调优指南

Code
索引选择决策树:

                    ┌─────────────────┐
                    │ 查询类型是什么?  │
                    └────────┬────────┘
                             │
              ┌──────────────┼──────────────┐
              │              │              │
        ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
        │ 精确匹配   │ │ 语义搜索   │ │ 全文检索   │
        │ 范围查询   │ │ 相似度    │ │ 关键词     │
        └─────┬─────┘ └─────┬─────┘ └─────┬─────┘
              │              │              │
        ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
        │ Prefix/   │ │  HNSW     │ │ Inverted  │
        │ Bitmap    │ │  Index    │ │  Index    │
        │ Index     │ │           │ │           │
        └───────────┘ └───────────┘ └───────────┘

#6.4 分区与分桶策略

SQL
-- 动态分区配置(自动管理月分区)
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 数据写入流程

Code
数据写入流程:

┌──────────┐     ┌─────────────┐     ┌──────────────┐
│ Control  │gRPC │ Data Layer  │     │   Doris      │
│  Layer   ├────>│ WriteService├────>│   (Stream    │
│ (B)      │     │             │     │    Load)     │
└──────────┘     └──────┬──────┘     └──────────────┘
                        │
                        │ async
                        v
                 ┌──────────────┐
                 │  Embedding   │
                 │  Service (D) │
                 │  (生成向量)   │
                 └──────┬───────┘
                        │
                        v
                 ┌──────────────┐
                 │ Doris UPDATE │
                 │ (embedding   │
                 │  column)     │
                 └──────────────┘

#7.2 查询服务架构

Python
# 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 服务定义

PROTOBUF
// 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 测试结果

Code
查询延迟分布 (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 资源使用

Code
集群资源使用情况(5 BE 节点平均):

CPU:     ██████████████░░░░░░  68%
Memory:  ████████████████░░░░  82%
Disk IO: ██████████░░░░░░░░░░  48%
Network: ████░░░░░░░░░░░░░░░░  22%

#9. 常见问题与解决方案

#9.1 向量索引构建慢

问题: 大表添加 HNSW 索引时,构建时间过长。

解决方案:

SQL
-- 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 近似搜索丢失部分相关结果。

解决方案:

SQL
-- 增加 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 中文分词效果不佳

问题: 默认分词器对专业术语处理不好。

解决方案:

SQL
-- 使用自定义词典
-- 在 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 其他组件的关系

Code
coomia-dip 存储层全景:

┌─────────────────────────────────────────────────┐
│                  Query Layer                     │
│  ┌──────────────────────────────────────────┐   │
│  │       QueryFederationService (C)          │   │
│  └──────┬──────────────────┬────────────────┘   │
│         │                  │                     │
│    ┌────┴─────┐      ┌────┴─────┐               │
│    │  Doris   │      │  DuckDB  │               │
│    │ (主引擎) │      │ (辅引擎) │               │
│    └────┬─────┘      └──────────┘               │
│         │                                        │
│    ┌────┴──────────────────────────────┐        │
│    │         Storage Layer              │        │
│    │  ┌─────────┐  ┌────────────────┐  │        │
│    │  │ MinIO   │  │ Nessie+Iceberg │  │        │
│    │  │ (对象)  │  │ (版本化湖仓)   │  │        │
│    │  └─────────┘  └────────────────┘  │        │
│    └────────────────────────────────────┘        │
└─────────────────────────────────────────────────┘

#Key Takeaways

  1. 统一引擎 > 专用引擎组合:在多模查询场景下,Doris 统一方案的联合查询性能比多引擎方案快 70-82%,同时大幅降低运维复杂度。

  2. HNSW 索引让 OLAP 引擎具备语义搜索能力:通过合理配置 M 和 ef 参数,可以在召回率和性能之间找到最佳平衡点。

  3. 倒排索引支持中文全文检索:Doris 内置的 unicode 分词器加上自定义词典,可以满足中文场景下的全文检索需求。

  4. 三合一查询是杀手级特性:在一条 SQL 中同时完成 OLAP 聚合 + 向量搜索 + 全文检索,这是任何多引擎方案都无法高效实现的。

  5. 合理的索引策略是性能关键:根据查询模式选择合适的索引类型(Prefix/Bitmap/HNSW/Inverted),并通过分区和分桶策略优化数据分布。

#Next Article

下一篇 S3-02《像 Git 一样管理数据:Nessie + Iceberg 实现数据版本控制》 将深入探讨如何使用 Nessie 和 Iceberg 为智策平台的数据层提供 Git 风格的版本控制能力,包括分支、合并、冲突解决和时间旅行查询。

Tags: #ApacheDoris #OLAP #VectorSearch #HNSW #InvertedIndex #FullTextSearch #智策平台 #coomia-dip #统一引擎 #数据基座