{T}

Elasticsearch 是如何建立索引的?

0. 引言

MySQL 的 LIKE '%关键词%' 无法命中索引,全表扫描在海量文本面前不可用。Elasticsearch(ES)倒排索引把"文档 → 词条"的关系反转成"词条 → 文档",实现毫秒级全文检索。它是日志分析、商品搜索、站内检索的事实标准。本文讲解 ES 的索引建立过程与核心机制。

1. 正排 vs 倒排:索引的本质区别

text
正排索引(MySQL 主键索引):
  文档 ID → 内容:"MySQL 教程"、"Java 并发编程"、"分布式系统"
  查询"编程" → 遍历所有文档 → 逐条匹配 → O(N) 全扫描

倒排索引(ES):
  词条 → 文档 ID 列表:
    "mysql"   → [doc1]
    "教程"    → [doc1]
    "java"    → [doc2]
    "编程"    → [doc2]
    "分布式"  → [doc3]
  查询"编程" → 直接定位 doc2 → O(1) 命中
维度正排索引倒排索引
结构文档 → 词条词条 → 文档
查询全文扫描慢词条定位快(毫秒级)
适用精确匹配、范围查询全文检索、模糊匹配

倒排索引中的每个词条还记录 Term Dictionary(词条字典)+ Posting List(倒排列表):字典按序排列支持二分查找,倒排列表记录文档 ID(压缩存储:增量编码 + 位图),并支持词频/位置信息用于相关度排序(TF-IDF/BM25)。

2. 文档写入:从 JSON 到倒排索引

图表渲染中…

2.1 分词(Analyzer)

写入时文本经过 Analyzer 处理:字符过滤 → 分词器 → Token 过滤器

text
"I'm learning MySQL 8.0" 
→ 小写化:i'm learning mysql 8.0
→ 分词:i'm / learning / mysql / 8.0
→ 停用词过滤(可选):learning / mysql / 8.0
  • 中文分词:IK 分词器(ik_max_word/ik_smart)、中文分词器(analysis-icu);不配置中文分词器时中文会被整句切分,检索效果差;
  • 检索时查询词也要走同一 Analyzer——"分词一致"是检索正确的前提。

2.2 近实时可见(NRT)

text
写入 → 内存 buffer(不可搜索)+ translog(崩溃恢复)
refresh(默认 1s)→ buffer 生成 segment(可搜索)
flush → segment 落盘 + translog 清空
merge → 小段合并大段(控制段数量)
  • ES 是近实时(Near Real Time):写入后约 1 秒可搜到(refresh 间隔可调:index.refresh_interval);
  • 为什么不是实时?批量积攒构建倒排索引成本更低;强实时场景可调 refresh_interval=1s 或依赖 ID 查询(_id 实时)。

3. 分布式架构:分片与副本

图表渲染中…
概念说明
索引(Index)逻辑命名空间,类似数据库的"表"
分片(Shard)索引数据的物理切片(默认 1 主分片,可配置),每个分片是独立 Lucene 索引
副本(Replica)主分片的拷贝:高可用 + 读扩展(读请求可分发到副本)
路由routing = hash(docId) % 分片数,定位文档所在分片

规划要点:分片数创建后不可修改(修改需重建索引)——按数据量与节点数预算;副本数可动态调整(PUT /index/_settings)。写入流程:客户端 → 主分片 → 同步副本(wait_for_active_shards 可配置)。

4. ES 与 MySQL 的配合

图表渲染中…
  • 双写/同步:业务写 MySQL(权威数据),通过 binlog 同步(Canal/Logstash)到 ES——MySQL 管事务,ES 管检索
  • 查询路径:ES 搜出文档 ID → 回 MySQL/Redis 查详情(避免 ES 存大字段);
  • 一致性:容忍秒级同步延迟(删改后短暂搜到旧数据,可配合软删除/版本号)。

5. 面试高频问题

  1. 倒排索引怎么实现的? 词条字典(排序 + 二分)→ 倒排列表(文档 ID 压缩存储 + 词频/位置);
  2. 为什么 ES 是近实时? refresh 间隔(默认 1s)批量生成段;translog 保证不丢数据;
  3. ES 和 MySQL 的定位? MySQL 强一致 + 事务;ES 全文检索 + 分析;两者互补;
  4. 如何优化 ES 写入? 批量写入(bulk)、合理副本数、调整 refresh/translog 参数、避免大字段。

6. 小结

  • ES 核心是倒排索引:词条 → 文档,全文检索毫秒级;
  • 写入链路:分析(分词)→ 倒排索引 → buffer+translog → refresh 段 → 落盘合并
  • 近实时(1s 可见)由 refresh 机制决定;分片 + 副本支撑水平扩展与高可用;
  • 与 MySQL 配合:MySQL 权威 + ES 检索,binlog 同步,容忍秒级延迟。

下一章进入消息队列篇:消息队列的应用场景与选型。