弹性搜索的delete_by_query功能是如何工作的?当我们插入新数据、同时删除文档并检索相同文档时会发生什么?

7
我想了解更多关于弹性删除的信息,它是Java高级删除API,是否可行进行批量删除。
以下是配置信息。
  • Java: 8
  • Elastic Version: 7.1.1
  • Elastic dependencies added:

    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.1.1</version>
    </dependency>
    
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>7.1.1</version>
    </dependency>
    
在我的情况下,每天大约会向索引“dev-answer”中添加10K条记录。我想触发删除操作(可以每天、每周或每月触发一次),如果满足特定条件,该操作将从上述“index”中删除所有文档。(我将在“DeleteByQueryRequest”中给出条件)。对于删除操作,最新的文档提供了一个API,我正在参考它。
DeleteByQueryRequest request = new DeleteByQueryRequest("source1", "source2");

在阅读文档时,我遇到了以下查询,我无法理解。

  1. 如文档中所述:也可以通过设置大小来限制处理的文档数量。request.setSize(10);“处理文档”是什么意思?它只会删除10个文档吗?

  2. 应该设置什么批处理大小?request.setBatchSize(100); 它的性能基于我们要删除多少个文档?

    我是否应该首先调用获取文档数,然后根据那个数字更改setBatchSize

  3. request.setSlices(2);切片应该取决于执行机器上有多少个内核或弹性集群中的内核数量?

  4. 文档中给出了setSlices(2)方法,但我却找不到org.elasticsearch.index.reindex.DeleteByQueryRequest类中的该方法。我错过了什么?

  5. 假设我以异步模式执行此删除查询,需要0.5-1.0秒,同时如果我在该索引上进行get请求,是否会出现异常? 同时,在同一时间如果我插入新文档并检索相同文档,它能否提供响应?


我有点困惑,肯定是通过查询删除,但在Java API中,我将使用org.elasticsearch.client.RestHighLevelClient类中的函数:public final void deleteByQueryAsync(DeleteByQueryRequest deleteByQueryRequest, RequestOptions options, ActionListener<BulkByScrollResponse> listener)。那么它会发出批量请求还是通过查询删除?此外,在删除超过10K的情况下,仅有不到1K的记录,哪种方法更好?delete_by_query还是_bulk - AshwinK
还有一个同步请求的函数是 deleteByQuery,它返回 BulkByScrollResponse。这就引起了混淆,不知道是 _bulk 删除还是 delete_by_query - AshwinK
好的,我已按建议修改了问题。谢谢。 - AshwinK
谢谢,但您能在标题中写delete_by_query而不是delete吗?这样可以避免混淆并帮助其他用户找到这个问题。delete也是另一个端点。我正在撰写完整的答案回复您的问题。 - Pierre-Nicolas Mougel
当然。我会做的。 - AshwinK
显示剩余2条评论
1个回答

5

1. 在文档中,通过设置大小,可以限制处理文档的数量。request.setSize(10); 这里的“处理文档”是什么意思?它只会删除10个文档吗?

如果您还没有阅读search/_scroll文档,请先阅读。 _delete_by_query使用给定的查询作为参数执行滚动搜索。

size参数对应每次调用scroll端点返回的文档数。如果有10个文档与您的查询匹配,并且大小为2,则Elasticsearch将在内部执行5个search/_scroll调用(即5个批次);而如果将大小设置为5,则只会执行2个search/_scroll调用。

无论size参数如何,所有匹配查询的文档都将被删除,但效率会更高或更低。

2. 我应该设置什么批量大小?request.setBatchSize(100); 它的性能基于我们要删除多少个文档?

setBatchSize()方法相当于在查询中设置size参数。您可以阅读this article来确定大小参数的正确值。

3.我应该先调用获取文档数量,然后根据此更改setBatchSize吗?

我认为您需要运行两次搜索请求才能获取删除文档的数量,这可能不是高效的。我建议您找到并坚持使用一个固定值。

4.片段应该基于执行器机器有多少个内核或弹性集群中的内核数量?

切片的数量应该从elasticsearch集群配置中设置。这也可以在分片之间和分片内部并行化搜索。

您可以阅读文档以获取有关如何设置此参数的提示。通常为索引设置的分片数。

5. 文档中给出了setSlices(2)方法,但我在org.elasticsearch.index.reindex.DeleteByQueryRequest类中找不到。我错过了什么?

您是正确的,那可能是文档中的错误。虽然我从未尝试过,但我认为您应该使用forSlice(TaskId slicingTask, SearchRequest slice, int totalSlices)

6. 假设我以异步模式执行此删除查询,需要0.5-1.0秒,同时如果我在此索引上进行get请求,会发生异常吗?同时,在同一时间,如果我插入新文档并检索相同文档,它能够给出响应吗?

首先,根据文档,_delete_by_query端点会创建索引的快照,并在该副本上工作。

对于get请求,这取决于文档是否已被删除。它永远不会发送异常,您将获得与检索现有文档或不存在的文档相同的结果。请注意,除非在搜索查询中指定了sort,否则文档的删除顺序未确定。

如果在处理过程中插入(或更新)文档,则即使该文档与_delete_by_query查询相匹配,该文档也不会被_delete_by_query端点考虑在内。这就是快照的用途。因此,如果您插入新文档,则可以检索它。同样,如果您更新现有文档,则如果该文档已被删除或更新但尚未删除,则会再次创建该文档。

顺便说一下,已删除的文档仍然可以进行搜索(即使delete_by_query任务已完成),直到进行refresh操作为止。

_delete_by_query 不支持 refresh 参数。文档中提到的 refresh 操作的请求返回是指可以有刷新参数的请求。如果您想强制刷新,可以使用 _refresh 端点。默认情况下,刷新操作每 1 秒发生一次。因此,一旦 _delete_by_query 操作在最多 1 秒后完成,已删除的文档将无法进行搜索。


1
你有没有考虑使用每日指数?这样你就可以直接删除整个索引,这样做会更便宜,因为你可以避免在大量删除后发生的所有合并。这种方法在性能上会更好(至少对于删除操作),而且实现起来也更容易。不过可能会存在过度分片的权衡。 - xeraa
非常感谢您提供详细的答案和文档链接。它澄清了很多概念。批处理文档意味着批处理大小应该取决于返回的数据大小。所以这与滚动限制无关,对吗?在 delete_by_query 中,批量限制用于将数据从当前索引复制到其快照,是吗? - AshwinK
@xeraa 是的,那个选项也有意义。但目前我并不考虑每日索引,除非删除操作有一些固定的周期性。只是好奇知道会有什么权衡? - AshwinK
我已经更新了答案,回答了你关于“刷新”操作的问题。我不确定我理解了你关于批量大小和滚动限制的问题。你所说的滚动限制是什么意思? - Pierre-Nicolas Mougel
@Pierre-NicolasMougel 滚动限制是指在调用 _search?scroll API 时提供 "size": 100 - AshwinK
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接