基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Elasticsearch 中的 Update(更新)和 Delete(删除)操作是如何实现的?

知识点图片

Elasticsearch(简称 ES)底层的核心依赖是 Lucene。要理解 ES 的更新(Update)和删除(Delete)机制,首先必须理解一个核心概念:Lucene 的段(Segment)是不可变的(Immutable)

这意味着一旦数据被写入到一个段文件中,就不能再被修改。

基于这个前提,ES 的更新和删除操作实际上采用了一种 “逻辑删除” + “追加写入” 的策略,具体实现如下:


1. Delete(删除)操作的实现

当你向 ES 发送一个删除请求时,数据并不会立即从磁盘文件中抹去。

  1. 逻辑删除(标记)

    • ES 会在内部维护一个名为 .del 的特殊文件。
    • 当执行删除操作时,ES 只是在该文件中将目标文档的 ID 标记为“已删除”。
    • 此时,该文档的数据依然存在于原本的 Segment 中,占用着磁盘空间。
  2. 搜索时的处理

    • 当你执行搜索请求时,ES 依然会扫描到这些被标记为删除的文档。
    • 但是,在返回结果之前,ES 会根据 .del 文件过滤掉这些文档,因此用户在搜索结果中看不到它们。

2. Update(更新)操作的实现

由于 Segment 不可修改,ES 无法像 MySQL 那样直接“原地修改”某一行数据。Update 本质上是:Delete(旧版本) + Index(新版本)。

具体流程如下:

  1. 读取(Read)
    • 如果是局部更新(Partial Update),ES 首先需要根据 ID 把旧文档的 _source 内容读取出来。
  2. 修改(Modify)
    • 在内存中修改数据(例如合并新字段、修改字段值)。
  3. 标记删除(Delete)
    • ES 将旧文档的 ID 在 .del 文件中标记为“已删除”(同上面的删除逻辑)。
  4. 写入新文档(Index)
    • ES 将修改后的新文档作为一个全新的文档写入到一个新的 Segment(或内存缓冲区)中。
    • 同时,该文档的 _version 版本号会加 1。

结论:在更新刚刚完成后,磁盘上实际上保存了两份数据(一份标记删除的旧数据,一份生效的新数据)。

3. 物理删除何时发生?(Segment Merge)

既然删除和更新都会导致旧数据残留并占用磁盘空间,那么这些垃圾数据什么时候会被真正清理呢?

答案是:段合并(Segment Merge) 阶段。

  1. 后台合并
    • ES 会在后台自动运行 Merge 任务,将许多小的 Segment 合并成更大的 Segment,以减少文件句柄开销并优化搜索速度。
  2. 物理清理
    • 在合并过程中,ES 会读取多个 Segment 的内容。
    • 此时,它会检查 .del 文件。被标记为删除的文档不会被复制到新的大 Segment 中
    • 合并完成后,旧的小 Segment(包含垃圾数据的)会被完全删除。
    • 这时,磁盘空间才会被真正释放。

4. 总结与性能影响

  • 空间占用:频繁的 Update 和 Delete 会导致磁盘空间暂时膨胀,直到 Merge 发生。
  • 搜索性能
    • 虽然搜索结果不包含已删除文档,但搜索过程依然需要扫描它们(然后跳过)。
    • 如果 .del 文件中记录了大量“墓碑”数据(Deleted Documents),会拖慢搜索速度。
  • 写放大:Update 操作比直接 Index 操作更重,因为它涉及读取旧数据、逻辑删除、写入新数据三个步骤。

一句话总结:
Elasticsearch 的删除是“打标记”,更新是“先标记删除旧的,再写入新的”,真正的物理清除发生在后台的段合并(Merge)过程中。

00:00
00:00