
1.3 Elasticsearch-索引、文档、字段、映射—与 MySQL 的类比
如果把 MySQL 比作“关系型世界里的老管家”,那 Elasticsearch(后文简称 ES)就是“搜索界的自由派艺术家”。两者都能存数据、都能查数据,但底层哲学截然不同:MySQL 强调“先定结构,后放数据”;ES 则允许“边写边改结构”,甚至鼓励冗余与反范式。要快速把 MySQL 的经验迁移到 ES,最省脑细胞的法子就是“类比”——把熟悉的表、行、列、Schema 一一对应到 ES 的索引、文档、字段、映射。下面用一张“直译表”先给出结论,再逐条拆坑。
| MySQL 概念 | ES 概念 | 类比关系 | 关键差异一句话 |
|---|---|---|---|
| database | cluster | 1:N | 一个集群可挂 N 个索引,database 只是逻辑隔离 |
| table | index | 1:1 | index 相当于“一张大宽表”,但无 JOIN |
| row | document | 1:1 | document 就是 JSON,自带 _id 主键 |
| column | field | 1:1 | field 类型可嵌套、可多值,无需先 ALTER |
| schema | mapping | 1:1 | mapping 只约束“倒排索引如何建”,不约束源码 JSON |
1.3.1 索引 ≠ 数据库,却是“最大粒度”的隔离单元
很多人第一次 Kibana 建索引时,下意识把 index 当成 database,结果一个业务库建了十几个 index,shard 爆炸。
正确姿势:
- 一个“业务实体”对应一个 index,比如
order、product。 - 如果日增量过 TB,再按时间滚动 (
order-2025-10),而不是按字段分 index。 - 集群级别设置(分片数、副本数)在 index 创建时固化,后续改=重建。
1.3.2 文档 = 行 + 超能力
MySQL 的行是“定长结构”,ES 的文档是“JSON 树”。
超能力 1:字段可以突然多出来
POST /user/_doc/1
{
"name": "alice",
"tags": ["coder", "coffee"] // 之前 mapping 里没有 tags 也能写
}
超能力 2:数组原生支持,无需另建表。
超能力 3:嵌套对象(nested)/父子文档(join)模拟 1-N,但性能代价远高于 MySQL 的 JOIN,必须预评估。
1.3.3 字段类型:ES 的“动态猜” vs MySQL 的“先声明”
MySQL 的 VARCHAR(32) 一旦定死,插 abcdef 超长直接报错。
ES 第一次见新字段,会“动态映射”:
- 字符串 → text + keyword 双字段
- 整型 → long
- 浮点 → float
- 日期 → date(能解析才认)
生产环境务必关掉 dynamic: true,改为 strict 或 runtime,否则某天有人塞了一个 ip 字段被识别成 text,聚合秒变噩梦。
1.3.4 Mapping:不是“锁结构”,而是“告诉 Lucene 怎么建倒排”
MySQL 的 DDL 一旦执行,表结构即刻硬化;ES 的 mapping 只影响“索引阶段”的倒排生成,已经存进去的文档不会被动迁。
典型坑:
- 想把
status从text改成keyword做聚合?需要 reindex。 - 想加子字段
title.keyword?可以用PUT mapping追加,但老数据不会自动回填,需要_update_by_query。 enabled: false的字段会完整存_source但不建倒排,相当于 MySQL 的“不建索引”。
1.3.5 主键:_id 与业务主键的博弈
MySQL 用 INT PK 或 UUID;ES 用 _id 字符串。
最佳实践:
- 如果业务本身有唯一键
order_no,直接拿它当_id,省去二次映射。 - 高并发写入时,让 ES 自生成
_id比指定_id快 2~3 倍(少了版本冲突检查)。 _id唯一性只在单 index 内保证,跨 index 可重复。
1.3.6 事务:没有 ACID,只有“单文档原子”
MySQL 的 BEGIN/COMMIT 可以跨多行;ES 的 bulk 只是“批打包”,其中任一文档失败不影响其他。
需要“事务级”一致性?只能客户端二次校验或走“版本号 + 乐观锁”套路:
PUT /account/_doc/1?if_seq_no=1024&if_primary_term=3
{ "balance": 900 }
失败返回 409 Conflict,业务层重试。
1.3.7 聚合:GROUP BY 的“光速版”与“内存杀手”
MySQL 的 GROUP BY 走 B+Tree 或临时文件;ES 的 terms agg 直接读倒排,亿级行毫秒回。
代价:
- 聚合结果默认“近似”,
shard_size太小会丢桶。 - 高基数字段(如
user_id千万级)做全聚合,Fielddata 会把内存打爆,需要cardinality或composite agg分页。
1.3.8 小结:一张脑图带走
MySQL world → Elasticsearch world
database → cluster(逻辑隔离最小单元)
table → index(分片在集群层)
row → document(JSON,_id 主键)
column → field(可嵌套、可多值)
schema DDL → mapping(只约束倒排,可追加)
JOIN → nested / join / 宽表冗余
GROUP BY → agg(近实时、内存敏感)
ACID → 单文档原子 + 乐观锁
记住一句话:
“索引像表,文档像行,字段像列,映射像 Schema,但别被类比绑架——ES 是搜索引擎,不是另一个 MySQL。”
更多技术文章见公众号: 大城市小农民
Elasticsearch与MySQL核心概念对比
2415

被折叠的 条评论
为什么被折叠?



