Elasticsearch:处理经常更新的文档
Elasticsearch: Working with frequently updated documents
我有一个论坛应用程序。论坛中有多个主题(帖子)。每个主题都有字段,例如viewCount
(论坛用户查看该主题的次数)。
我希望主题的所有字段都取自 ES(id、日期、标题、内容和 viewCount)。然而,在这种情况下,在每个主题视图之后,ES 必须重新索引整个文档。
我问了关于堆栈溢出部分更新的问题 - 。重要的是要注意 viewCount
字段没有索引,它只是存储在 ES 中。
有两个术语 - 部分更新和部分索引。 ES 中有部分更新,您只能更改几个字段。但是没有部分重新索引,这意味着即使你只更改一个字段,ES 也会重新索引整个文档。这意味着如果该主题被查看 1000 次,ES 将对其进行索引 1000 次。如果我有很多用户,许多文档将被一次又一次地索引。这是第一个策略。
第二种策略是将主题的一些字段保留在索引中,一些保留在数据库中。在这种情况下,我可以从数据库中获取 viewAcount。此外,然后我可以将所有字段存储在数据库中,并将索引仅用作索引,即获取当前主题的 ID。
解决此类问题的最佳方法是什么?
我想最好的方法是重新考虑您的索引设计。创建另一个索引可能是有意义的,它具有较少的字段数量,因此 index/update 成本较低,它将 id 映射到它们各自的视图计数。然后您的客户端可以发出两个查询以获取所有必需的信息。
关于文档的部分更新,重要的是要认识到,虽然 API 让您执行部分更新,但在幕后,它通过检索文档、更改文档和重新索引来执行完整更新它。以下来自 Elasticsearch 网站:
In Updating a Whole Document, we said that the way to update a document is to retrieve it, change it, and then reindex the whole document. This is true. However, using the update API, we can make partial updates like incrementing a counter in a single request.
We also said that documents are immutable: they cannot be changed, only replaced. The update API must obey the same rules. Externally, it appears as though we are partially updating a document in place. Internally, however, the update API simply manages the same retrieve-change-reindex process that we have already described. The difference is that this process happens within a shard, thus avoiding the network overhead of multiple requests. By reducing the time between the retrieve and reindex steps, we also reduce the likelihood of there being conflicting changes from other processes.
要既将全文数据存储在 Elasticsearch 中,又要在不重新索引整个文档的情况下经常更改字段,您需要将这些项目存储在其他地方。这可以是另一个 Elasticsearch 索引或另一个系统中的元数据/计数器存储。
对于常见用例,您可以运行 对两者使用相同的查询并合并结果。这些很可能是简单的过滤器,并且对不会更改的字段进行排序,例如主题、创作时间、作者等
对于不匹配的搜索,例如全文查询,您可以 (a) 不显示该数据,或者 (b) 使用最终一致的方法,定期更新 Elasticsearch 主题存储更新计数。许多对一致性要求不高的系统可以使用最终一致性方法,包括 Stack Overflow、Netflix 等。例如,在某些网站上,您会在一个页面/小部件上获得一个计数,而在另一个页面/上获得另一个计数/小部件由于最终一致的设计。
对我来说,似乎在使用 ES 的情况下,您应该只更新索引中的所有数据并对其进行查询。如果您将拆分文本(据我所知,您将主题存储在 ES 中用于文本搜索)和数据存储之间的 "digital" 数据,与在 ES 中重新索引文档的情况相比,您将遇到更大的性能损失。
ES 唯一可以对索引中的文档执行的操作 - 索引和删除。因此,有两种方法可以加快重新索引
加速 "payload" - 减少删除文档和
再次索引它。这可以实现移动 ES index to memory,以利用 Lucene 的 RamIndexStore
减少网络开销 - 在 ES 端使用 scripts
执行操作
顺便说一句,您是否已经遇到性能问题?
我有一个论坛应用程序。论坛中有多个主题(帖子)。每个主题都有字段,例如viewCount
(论坛用户查看该主题的次数)。
我希望主题的所有字段都取自 ES(id、日期、标题、内容和 viewCount)。然而,在这种情况下,在每个主题视图之后,ES 必须重新索引整个文档。
我问了关于堆栈溢出部分更新的问题 - viewCount
字段没有索引,它只是存储在 ES 中。
有两个术语 - 部分更新和部分索引。 ES 中有部分更新,您只能更改几个字段。但是没有部分重新索引,这意味着即使你只更改一个字段,ES 也会重新索引整个文档。这意味着如果该主题被查看 1000 次,ES 将对其进行索引 1000 次。如果我有很多用户,许多文档将被一次又一次地索引。这是第一个策略。
第二种策略是将主题的一些字段保留在索引中,一些保留在数据库中。在这种情况下,我可以从数据库中获取 viewAcount。此外,然后我可以将所有字段存储在数据库中,并将索引仅用作索引,即获取当前主题的 ID。
解决此类问题的最佳方法是什么?
我想最好的方法是重新考虑您的索引设计。创建另一个索引可能是有意义的,它具有较少的字段数量,因此 index/update 成本较低,它将 id 映射到它们各自的视图计数。然后您的客户端可以发出两个查询以获取所有必需的信息。
关于文档的部分更新,重要的是要认识到,虽然 API 让您执行部分更新,但在幕后,它通过检索文档、更改文档和重新索引来执行完整更新它。以下来自 Elasticsearch 网站:
In Updating a Whole Document, we said that the way to update a document is to retrieve it, change it, and then reindex the whole document. This is true. However, using the update API, we can make partial updates like incrementing a counter in a single request.
We also said that documents are immutable: they cannot be changed, only replaced. The update API must obey the same rules. Externally, it appears as though we are partially updating a document in place. Internally, however, the update API simply manages the same retrieve-change-reindex process that we have already described. The difference is that this process happens within a shard, thus avoiding the network overhead of multiple requests. By reducing the time between the retrieve and reindex steps, we also reduce the likelihood of there being conflicting changes from other processes.
要既将全文数据存储在 Elasticsearch 中,又要在不重新索引整个文档的情况下经常更改字段,您需要将这些项目存储在其他地方。这可以是另一个 Elasticsearch 索引或另一个系统中的元数据/计数器存储。
对于常见用例,您可以运行 对两者使用相同的查询并合并结果。这些很可能是简单的过滤器,并且对不会更改的字段进行排序,例如主题、创作时间、作者等
对于不匹配的搜索,例如全文查询,您可以 (a) 不显示该数据,或者 (b) 使用最终一致的方法,定期更新 Elasticsearch 主题存储更新计数。许多对一致性要求不高的系统可以使用最终一致性方法,包括 Stack Overflow、Netflix 等。例如,在某些网站上,您会在一个页面/小部件上获得一个计数,而在另一个页面/上获得另一个计数/小部件由于最终一致的设计。
对我来说,似乎在使用 ES 的情况下,您应该只更新索引中的所有数据并对其进行查询。如果您将拆分文本(据我所知,您将主题存储在 ES 中用于文本搜索)和数据存储之间的 "digital" 数据,与在 ES 中重新索引文档的情况相比,您将遇到更大的性能损失。
ES 唯一可以对索引中的文档执行的操作 - 索引和删除。因此,有两种方法可以加快重新索引
加速 "payload" - 减少删除文档和 再次索引它。这可以实现移动 ES index to memory,以利用 Lucene 的
RamIndexStore
减少网络开销 - 在 ES 端使用 scripts
执行操作
顺便说一句,您是否已经遇到性能问题?