惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
Hacker News: Ask HN
Hacker News: Ask HN
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
The Exploit Database - CXSecurity.com
The Hacker News
The Hacker News
Security Latest
Security Latest
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Scott Helme
Scott Helme
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
WordPress大学
WordPress大学
雷峰网
雷峰网
L
LangChain Blog
Y
Y Combinator Blog
I
Intezer
V
Vulnerabilities – Threatpost
Apple Machine Learning Research
Apple Machine Learning Research
The Last Watchdog
The Last Watchdog
Simon Willison's Weblog
Simon Willison's Weblog
W
WeLiveSecurity
P
Privacy International News Feed
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
AI
AI
博客园 - Franky
Hacker News - Newest:
Hacker News - Newest: "LLM"
Martin Fowler
Martin Fowler
K
Kaspersky official blog
U
Unit 42
S
Schneier on Security
Webroot Blog
Webroot Blog
Know Your Adversary
Know Your Adversary
T
Tor Project blog
aimingoo的专栏
aimingoo的专栏
Engineering at Meta
Engineering at Meta
G
GRAHAM CLULEY
美团技术团队
TaoSecurity Blog
TaoSecurity Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Google DeepMind News
Google DeepMind News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
P
Proofpoint News Feed
爱范儿
爱范儿
F
Fortinet All Blogs
有赞技术团队
有赞技术团队

博客园 - 许仙儿

从大括号圣战到人机掰手腕:AI时代,程序员的“累”换了个赛道 Git 文件忽略备忘录:`assume-unchanged` 完全指南 用go写一个微服务gPRC为主RESTful为辅 三号车间张三喜 为什么湖广不太吃鲤鱼 为什么夏天副高会导致伏旱,而冬天的西伯利亚高原又会带来寒流 普通RESTful和MCP调用对比 2026年放假安排 红楼梦龄官病死前和贾蔷同居的情节 古代的时辰,几更天与现在的时间对应关系是什么? 西游记结局评职称 生成一张图,苹果logo是透明冰块,安卓小机器人撒尿到苹果logo,冲出一个豁口 HL7v3和RIM是什么,和传统HL7,FHIR有什么关系 owl(Web Ontology Language)简介 早上看到木蜂在抓取掉落到地上的国槐花,还一边打滚。它是否习性懒惰? Java SPI(Service Provider Interface)示例 常见古文中流行度和水平最高的前100首,按朝代分类 API Blueprint​​ 是一种基于 ​​Markdown​​ 的轻量级 API 描述语言 八卦的符号,读音,名称,代表的事务分别是什么 Spring Boot 中 JdbcTemplate、MyBatis 和 JPA 共用数据源的可行性 win10下python程序报错OPENSSL_Uplink(00007FFD0AC12FE8,08): no OPENSSL_Applink
关系型数据库 vs Elasticsearch
许仙儿 · 2025-09-25 · via 博客园 - 许仙儿

关系型数据库 vs Elasticsearch:存储、索引与查询的深度对比

本文将用图文结合的方式,深入探讨两种技术在数据存储、索引机制和查询性能方面的核心差异,帮助您做出更明智的技术选型。

一、引言:两种不同的设计哲学

关系型数据库(如MySQL/PostgreSQL)Elasticsearch 代表了两种截然不同的数据处理哲学:

  • RDBMS:为事务一致性而生,遵循ACID原则,擅长处理结构化数据
  • Elasticsearch:为搜索分析而生,追求极致的查询性能,擅长处理半结构化数据

让我们通过一个直观的比喻来理解:

  • RDBMS像一本精心编排的图书馆:每本书都有固定位置,借阅需要严格登记
  • ES像一个超级搜索引擎:能瞬间从海量书籍中找到所有相关内容

graph LR A[RDBMS] --> B[("图书馆模型<br/>严格有序")] C[Elasticsearch] --> D[("搜索引擎模型<br/>快速检索")]

二、存储结构对比

2.1 关系型数据库:行式存储

RDBMS采用行式存储,将整行数据连续存储在磁盘上:

ID Name Age Diagnosis Tags
1 张三 25 感冒, 肺炎 发热, 咳嗽
2 李四 34 高血压 头晕, 测量异常
3 王五 28 糖尿病 多饮, 多尿

特点

  • 数据按行连续存储,读取整行数据效率高
  • 适合OLTP(联机事务处理)场景
  • 表结构固定,需要预先定义Schema

2.2 Elasticsearch:文档式存储 + 列式存储

ES采用混合存储策略,兼具文档式和列式存储的优点:

文档存储(_source字段)

{
  "patient_id": "001",
  "name": "张三",
  "age": 25,
  "diagnosis": ["感冒", "肺炎"],
  "tags": ["发热", "咳嗽", "呼吸道感染"]
}

列式存储(Doc Values)

诊断字段Doc Values:
感冒    → [文档1, 文档5, 文档8, ...]
肺炎    → [文档1, 文档3, 文档7, ...]
高血压  → [文档2, 文档4, 文档9, ...]

标签字段Doc Values:
发热   → [文档1, 文档6, 文档11, ...]
咳嗽   → [文档1, 文档3, 文档8, ...]

特点

  • 原始文档完整存储(便于重建)
  • 每个字段单独存储为列式结构(便于聚合分析)
  • Schema灵活,支持动态映射

三、索引机制深度解析

3.1 RDBMS:B-Tree/B+Tree索引

B+Tree是RDBMS最常用的索引结构,适合范围查询和排序:

graph TD A[根节点] --> B[内部节点] A --> C[内部节点] B --> D[叶子节点: 1-100] B --> E[叶子节点: 101-200] C --> F[叶子节点: 201-300] C --> G[叶子节点: 301-400] D --> H[数据页: 记录1] D --> I[数据页: 记录2] E --> J[...] linkStyle 4,5,6,7 stroke:#ccc,stroke-width:1px

工作流程

  1. 从根节点开始二分查找
  2. 逐层向下遍历内部节点
  3. 到达叶子节点找到目标数据位置
  4. 通过指针访问实际数据页

优势

  • 平衡树结构,查询稳定 O(log N)
  • 支持范围查询、排序、唯一约束
  • 叶子节点链表连接,适合范围扫描

3.2 Elasticsearch:倒排索引 + 优化结构

ES的核心是倒排索引,但针对不同场景有深度优化:

基础倒排索引结构

词项(Term)   文档ID列表(Posting List)
感冒        → [1, 5, 8, 13, 25, ...]
肺炎        → [1, 3, 7, 13, 22, ...]
发热        → [1, 6, 8, 11, 13, ...]

优化层次结构

graph TD A[倒排索引] --> B[词项字典 Term Dictionary] A --> C[文档ID列表 Posting Lists] B --> D[索引结构优化] D --> E[FST<br/>压缩词项字典] D --> F[Skip List<br/>加速链表遍历] C --> G[压缩优化] G --> H[FOR编码<br/>帧间压缩] G --> I[Roaring Bitmaps<br/>位图压缩] E --> J[内存效率] F --> K[查询速度] H --> L[存储空间] I --> M[集合运算]

关键优化技术

  1. FST(有限状态转换器):压缩存储词项字典,内存占用极小
  2. Frame of Reference编码:对有序数字ID进行差分压缩
  3. Roaring Bitmaps:将常用过滤条件转换为位图,利用CPU位运算

四、查询性能对比分析

4.1 为什么ES通常更快?

让我们通过一个具体例子来说明:查询同时患有"感冒"和"肺炎"的患者

RDBMS查询流程:

SELECT p.* 
FROM patients p
JOIN patient_tags pt1 ON p.id = pt1.patient_id 
JOIN tags t1 ON pt1.tag_id = t1.id AND t1.name = '感冒'
JOIN patient_tags pt2 ON p.id = pt2.patient_id  
JOIN tags t2 ON pt2.tag_id = t2.id AND t2.name = '肺炎';

执行过程(涉及大量磁盘IO和JOIN操作):

graph LR A[查询解析] --> B[索引查找感冒标签] A --> C[索引查找肺炎标签] B --> D[获取感冒患者ID集合] C --> E[获取肺炎患者ID集合] D --> F[内存JOIN操作] E --> F F --> G[回表查询患者详情] G --> H[返回结果]

Elasticsearch查询流程:

{
  "query": {
    "bool": {
      "must": [
        { "term": { "tags.keyword": "感冒" } },
        { "term": { "tags.keyword": "肺炎" } }
      ]
    }
  }
}

执行过程(内存中的高效集合运算):

graph LR A[查询解析] --> B[倒排索引查找] B --> C[获取感冒Posting List] B --> D[获取肺炎Posting List] C --> E[位图AND运算] D --> E E --> F[从_source获取详情] F --> G[返回结果]

4.2 性能差异根源

对比维度 RDBMS Elasticsearch
数据定位 需要多次索引查找+JOIN 直接倒排索引定位
集合运算 在应用层或数据库层做JOIN CPU级别的位运算
IO模式 随机IO较多(尤其大数据量) 顺序读取+内存计算
缓存机制 缓存数据页 缓存过滤结果(Bitset)

五、空间与时间的权衡

5.1 ES确实"用空间换速度"

Elasticsearch通过增加存储开销来换取查询性能:

空间开销主要来自

  1. 倒排索引:原始文本被分解为多个词项,每个词项都需要存储映射关系
  2. Doc Values:每个字段都有列式存储副本,用于聚合排序
  3. _source字段:存储原始文档完整副本
  4. 索引冗余:同一字段可能被多种方式索引(text、keyword等)

空间占用对比示例(100万条病历记录):

存储内容 RDBMS大小 ES大小 倍数
原始数据 500MB 500MB 1x
主键索引 100MB - -
倒排索引 - 1.5GB 15x
Doc Values - 800MB 8x
总占用 ~600MB ~2.8GB 4.7x

5.2 但这不是简单的交换

ES的空间开销带来了实实在在的价值:

  • 查询性能提升10-100倍
  • 支持复杂的多维度筛选
  • 实时聚合分析能力
  • 横向扩展性

六、场景优势分析

6.1 ES有明显优势的场景

1. 标签检索与筛选(最强项)

// 多标签组合查询:发热、咳嗽、但不包含肺炎的男性患者
{
  "query": {
    "bool": {
      "must": [
        { "terms": { "tags": ["发热", "咳嗽"] } },
        { "term": { "gender": "男" } }
      ],
      "must_not": [
        { "term": { "tags": "肺炎" } }
      ]
    }
  }
}

优势:毫秒级响应,即使数据量达到亿级

2. 全文搜索

// 在病历描述中搜索"持续性头痛伴有恶心"
{
  "query": {
    "match": {
      "description": "持续性头痛伴有恶心"
    }
  }
}

优势:分词搜索、相关性评分、模糊匹配

3. 聚合分析

// 统计各年龄段患者的疾病分布
{
  "size": 0,
  "aggs": {
    "age_groups": {
      "range": {
        "field": "age",
        "ranges": [
          { "to": 18 }, { "from": 18, "to": 35 },
          { "from": 35, "to": 50 }, { "from": 50 }
        ]
      },
      "aggs": {
        "diseases": {
          "terms": { "field": "diagnosis.keyword" }
        }
      }
    }
  }
}

优势:实时多维分析,秒级响应

4. 地理空间搜索

// 查找距离某医院5公里内的发热患者
{
  "query": {
    "bool": {
      "must": { "term": { "tags": "发热" } },
      "filter": {
        "geo_distance": {
          "distance": "5km",
          "location": { "lat": 39.9, "lon": 116.4 }
        }
      }
    }
  }
}

6.2 ES优势不明显的场景

1. 精确点查询(主键查询)

-- RDBMS更适合
SELECT * FROM patients WHERE id = '12345';

原因:ES的倒排索引对高基数字段效率较低

2. 复杂事务操作

-- 需要事务保证的操作
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

原因:ES不支持ACID事务,只有基本的一致性保证

3. 复杂关联查询

-- 多表深度关联
SELECT p.*, d.name, t.phone 
FROM patients p
JOIN departments d ON p.dept_id = d.id
JOIN doctors t ON p.doctor_id = t.id
WHERE d.specialty = '心脏病科'
AND t.title = '主任医师';

原因:ES不是为关联查询设计的,需要数据冗余或应用层处理

4. 频繁的数据更新

原因:ES的索引更新成本较高,涉及倒排索引重建

七、实际架构建议

混合架构:发挥各自优势

在实际生产环境中,通常采用混合架构:

graph TD A[应用系统] --> B{Router} B -->|事务操作| C[RDBMS<br/>MySQL/PostgreSQL] B -->|搜索分析| D[Elasticsearch<br/>搜索集群] C --> E[数据同步] D --> E E --> F[ETL/CDC工具<br/>Canal/Logstash] F --> D

分工明确

  • RDBMS:负责核心业务数据、事务处理、复杂关联查询
  • Elasticsearch:负责搜索、筛选、聚合分析、日志处理

八、总结

通过本文的对比分析,我们可以得出以下结论:

  1. ES的快速不是魔法:源于倒排索引、列式存储、内存计算等系统级优化
  2. 空间换时间是值得的:在存储成本大幅下降的今天,用存储空间换取查询性能是合理的权衡
  3. 没有银弹:ES在搜索分析场景表现卓越,但在事务处理和复杂关联方面不如RDBMS
  4. 混合架构是趋势:结合两者的优势,构建既能保证数据一致性又能提供高效检索的系统

技术选型建议

  • 如果需要强大的搜索、过滤、聚合能力,选择Elasticsearch
  • 如果需要严格的事务一致性、复杂关联查询,选择关系型数据库
  • 在大多数现代应用中,同时使用两者是最佳方案

希望这篇详细的对比能帮助您更好地理解两种技术的差异,并在实际项目中做出明智的技术决策。