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

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 1、从两个实战问题开始....问题1:elasticsearch-head 插件索引文档数显示结果不一致?

image.png

链接

image.png

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

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

image.png

问题来源:https://elasticsearch.cn/question/11238


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


2、文档版本号_version

在 Mysql 中插入一条记录,我们直观显示的是一行记录。而 Elasticsearch 是文档型搜索引擎,我们直观看到的是一条 json 记录。如下图所示:


_id 代表的唯一 id;


_version 代表的文档的版本号。

image.png

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


看个 demo 一探究竟。


DELETE test

# 执行一次

PUT test/_doc/1

{

   "counter" : 2,

   "tags" : ["blue"]

}

# "_version" : 1,

GET test/_doc/1

# "count" : 1, "deleted" : 0

GET test/_stats

# 再执行一次(更新操作)

#  "_version" : 2(版本号 + 1),

PUT test/_doc/1

{

   "counter" : 3,

   "tags" : ["blue","green"]

}

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

image.png

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

1. # "count" : 1, "deleted" : 1
2. GET test/_stats


image.png

如下执行 delete 操作后,看下 version 结果:_version 的版本号 + 1。


DELETE test/_doc/1

{

 "_index" : "test",

 "_type" : "_doc",

 "_id" : "1",

 "_version" : 3,

 "result" : "deleted",

 "_shards" : {

   "total" : 2,

   "successful" : 1,

   "failed" : 0

 },

 "_seq_no" : 2,

 "_primary_term" : 1

}

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

image.png

由此,初步得出结论:


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


同时,原来的老版本的文档标记为:deleted 状态,这里能解释问题 2:只重复写入也会有文档标记为 deleted 状态。


3、文档删除、索引删除、文档更新的本质?

3.1 删除文档的本质

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


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


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


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


POST test/_forcemerge?only_expunge_deletes

段合并中参数:“only_expunge_deletes“ 的含义只清除已标记为 deleted 的文档。


# "count" : 0, "deleted" : 0

GET test/_stats

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


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


3.2 索引删除的本质

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


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


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


索引删除包含两个步骤:


更新集群;


分片从磁盘删除。


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


删除索引操作如下:


DELETE test

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)一个全新的文档。同删除文档一样,旧文档不能被访问,但,旧文档不会被立即物理删除,除非手动或者定时执行了段合并操作。


4、再来看开篇两个问题

4.1  docs 文档数不一致怎么来的?

我们直接复现一下,再结合上两节的原理给出结论。直接拿 kibana_电商数据(kibana自带)样例数据作为基础数据。


第一步:原始数据大小:都是4675。

image.png

第二步:执行批量删除操作。删除:order_id > 584670 的数据。


POST kibana_sample_data_ecommerce/_delete_by_query

{

 "query":{

   "range":{

     "order_id":{

       "gt": 584670

     }

   }

 }

}

返回结果数:


{

 "took" : 100,

 "timed_out" : false,

 "total" : 1246,

 "deleted" : 1246,

 "batches" : 2,

......

}

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


第三步:再查看结果:

image.png

docs 两个值的变化:原来值是第一步截图值:4675。


4675-1246 = 3429 ,初步看:代表文档数精确值大小。


4675+1246 = 5921,初步看:代表文档原有数量 + deleted 文档数大小。


看一下:_stats 的统计如下:


GET kibana_sample_data_ecommerce/_stats

返回结果:


 "_all" : {

   "primaries" : {

     "docs" : {

       "count" : 3429,

       "deleted" : 2492

     },

第一个值大小就是:count;


第二个值大小就是:count + 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 文档就没有了。


5、小结

由一个小问题引发的思考和总结。

参考:


https://t.zsxq.com/zfiIIur


https://www.elastic.co/cn/blog/lucenes-handling-of-deleted-documents


Elasticsearch 官方文档


Elasticsearch 7.X cookbook 英文版


推荐

关于 Elasticsearch 段合并,这一篇说透了!


干货 | 论Elasticsearch数据建模的重要性


从一个实战问题再谈 Elasticsearch 数据建模


从实战中来,到实战中去——Elasticsearch 技能更快提升方法论

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
7月前
Elasticsearch之RestClient查询文档
Elasticsearch之RestClient查询文档
177 1
|
7月前
|
JSON 自然语言处理 数据库
数据库-ElasticSearch入门(索引、文档、查询)
数据库-ElasticSearch入门(索引、文档、查询)
386 0
|
3月前
|
JSON 自然语言处理 算法
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
DSL查询文档、RestClient查询文档、全文检索查询、精准查询、复合查询、地理坐标查询、分页、排序、高亮、黑马旅游案例
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
|
3月前
|
JSON 自然语言处理 数据库
ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入
概念、ik分词器、倒排索引、索引和文档的增删改查、RestClient对索引和文档的增删改查
ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入
|
4月前
|
存储 搜索推荐 API
探究:Elasticsearch 文档的 _id 是 Lucene 的 docid 吗?
【8月更文挑战第31天】在深入探索Elasticsearch(简称ES)这一强大的搜索引擎时,了解其底层存储机制——特别是与Lucene的关系,对于优化查询性能、设计高效的数据模型至关重要。其中,一个常见且容易引发误解的问题便是:Elasticsearch中文档的_id字段是否直接等同于Lucene的docid?本文将通过图文并茂的方式,详细剖析这一问题,帮助读者理解两者之间的微妙关系。
99 0
|
4月前
|
JSON 测试技术 API
黑马商城 Elasticsearch从入门到部署 RestClient操作文档
这篇文章详细介绍了如何使用Java的RestHighLevelClient客户端与Elasticsearch进行文档操作,包括新增、查询、删除、修改文档以及批量导入文档的方法,并提供了相应的代码示例和操作步骤。
|
4月前
|
JSON 自然语言处理 Java
Elasticsearch从入门到部署 文档操作 RestAPI
这篇文章详细介绍了Elasticsearch中文档的增删改查操作,并通过Java的RestHighLevelClient客户端演示了如何通过REST API与Elasticsearch进行交云,包括初始化客户端、索引库的创建、删除和存在性判断等操作。
|
4月前
|
消息中间件 监控 数据挖掘
Elasticsearch 使用误区之二——频繁更新文档
【8月更文挑战第15天】在大数据与搜索技术日益成熟的今天,Elasticsearch 作为一款分布式、RESTful 风格的搜索与数据分析引擎,凭借其强大的全文搜索能力和可扩展性,成为了众多企业和开发者的首选。然而,在使用 Elasticsearch 的过程中,一些常见的误区可能会导致性能下降或数据不一致等问题,其中“频繁更新文档”便是一个不容忽视的误区。本文将深入探讨这一误区的根源、影响及解决方案,帮助读者更好地利用 Elasticsearch。2
83 0
|
4月前
|
自然语言处理 Java 索引
ElasticSearch 实现分词全文检索 - Java SpringBoot ES 文档操作
ElasticSearch 实现分词全文检索 - Java SpringBoot ES 文档操作
44 0
|
5月前
|
存储 SQL 自然语言处理
Elasticsearch 索引与文档的常用操作总结二:复杂条件查询
Elasticsearch 索引与文档的常用操作总结二:复杂条件查询
176 0