Elasticsearch 中为什么会有大量文档插入后变成 deleted?

r660926
发布于 2022-4-22 16:46
浏览
0收藏

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

问题2:批量写入 ES 数据,大量文档状态变成 deleted,什么原因?


数据库读数据,批量插入到es里,id自定义用的数据库的主键值,批量插入后,没有报错,可是用cerebro看,大量文档的状态是deleted,数据库中的主键值百分百没有重复的,不知道为什么会这样?

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

以上两个问题都会涉及文档的删除、更新操作,下面我们先说透两个概念,然后再拆解分析问题就容易的多。

 

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区
在 Mysql 中插入一条记录,我们直观显示的是一行记录。而 Elasticsearch 是文档型搜索引擎,我们直观看到的是一条 json 记录。如下图所示:

 

 •  _id 代表的唯一 id;

 

 •  _version 代表的文档的版本号。
 Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

这时候,我们通常会有疑问?如果对已有数据执行更新或者删除操作后,版本号如何变化?


看个 demo 一探究竟。

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

再次写入文档相当于对原有文档执行更新全更新操作,_version 由 1 变成 2。

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

此时,我们再通过 _stats API 发现:deleted 显示为 3。

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

由此,初步得出结论:

 

 •  更新、删除操作实际是在原来文档的基础上版本号 + 1,且每执行一次,版本号 +1 一次。

 •  同时,原来的老版本的文档标记为:deleted 状态,这里能解释问题 2:只重复写入也会有文档标记为 deleted 状态。
Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区
3.1 删除文档的本质


 •  删除文档本质:逻辑删除而非物理删除。


在执行删除文档后,待删除文档不会立即将文档从磁盘中删除,而是将文档标记为已删除状态(版本号 _version + 1,  "result" 标记为:"deleted",)。最直观的反应就是被经常问到的问题“怎么删除文档后,磁盘空间不降?

 

随着不断的索引更多的数据,Elasticsearch 将会在后台清理标记为已删除的文档。

 

如果想要从磁盘上删除,需要借助段合并来实现,具体实践参考:

 

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

 

这里不免引申出一个问题,既然文档越删越多,对于历史的冷数据想批量或者全量删除,有没有更快的方式呢?

 

有的,借助删除索引来删除该索引下的全部数据。

 

3.2 索引删除的本质


不同于删除文档,删除索引意味着删除其分片、映射和数据。

 

索引删除本质:物理删除数据。

 

不同于文档的删除,索引删除会更直接、快速、暴力。删除索引后,与索引有关的所有数据将从直接从磁盘中删除。

 

索引删除包含两个步骤:

 

 •  更新集群;
 •  分片从磁盘删除。


这里要强调的是:如果没有索引快照备份或者其他数据备份存在,已删除的索引不可恢复(这个问题至少被问到 10次 +)。

 

删除索引操作如下:

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

3.2 更新文档的本质


更新文档的本质:delete + add。

 

In Lucene, the core engine of Elasticsearch, inserting or updating a document has thesame cost: in Lucene and Elasticsearch, to update means to replace.

 

表面上是更新,实际上是:Elasticsearch 将旧文档标记为已删除(deleted),并增加(add)一个全新的文档。同删除文档一样,旧文档不能被访问,但,旧文档不会被立即物理删除,除非手动或者定时执行了段合并操作。

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区
4.1  docs 文档数不一致怎么来的?


我们直接复现一下,再结合上两节的原理给出结论。直接拿 kibana_电商数据(kibana自带)样例数据作为基础数据。Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

 

返回结果数:

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

也就是说,共删除了:1246 条记录。

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区这里:deleted 为什么是:2492 = 1246 的2倍。我理解的是(欢迎就这个问题探讨):

 

 •  原有待删除文档大小:1246
 •  删除执行后,标记为:deleted, version + 1的文档数:1246。


实际测试验证中,大家会看到 deleted 值会变化:最早:2492, 然后变为:1246 ,最后变为:0。

 

当然,也可以使用 force_merge 强制段合并实现。

 

4.2 大量文档的状态是deleted,为什么?


我猜测:同步的时候,有相同 id 的文档数据写入了。也就是说:同一条数据写入了两次或多次,这样在 Elasticsearch 里面会做覆盖处理(本质是更新)。

 

而如前所述,更新的本质是:原有文档标记为已删除,然后再插入一条文档。

 

所以,可以尝试手动执行一下 force merge 操作,deleted 文档就没有了。 或者,自然等一段时间,待段合并的时机,deleted 文档就没有了。

Elasticsearch 中为什么会有大量文档插入后变成 deleted?-鸿蒙开发者社区

分类
收藏
回复
举报
回复
    相关推荐