ElasticSearch:使用频繁更改字段的最佳实践

iih3973s  于 2023-10-17  发布在  ElasticSearch
关注(0)|答案(2)|浏览(212)

我的文档中有一些字段每分钟有数百次更新,例如下载计数器,喜欢。
知道更改这些字段并重新索引的成本很高,更新这些字段的最佳方法是什么?
然而,仍然有一个,这些字段用于排序,因此将这些字段分隔在另一个索引中似乎不是执行排序的好方法,因为我的索引已经有超过40k的文档。我看不出有什么有效的办法。
我们使用的一种方法是索引,这是在其他索引中分离喜欢和下载,在搜索过程中,我们使用聚合进行计数,它工作得很好,但我们不能按喜欢或下载排序,因为它们在单独的索引中。
我们该如何处理这件事?

tf7tbtn2

tf7tbtn21#

在elasticsearch中更改字段值是昂贵的,因为在内部它实际上并不支持它。每一次更改都会导致一条旧记录被删除,而一条新记录将所有更新和未更新的字段编入索引。反过来,这些添加和删除的记录会导致不断的合并变动。
一个可能的解决方案是将记录分为两部分-一个大部分将包含很少(或最好是从不)更改的字段,另一个较小的部分将包含频繁更新的字段。这两个部分将在同一个索引中建立索引,但为了保留大部分和相应小部分之间的关系,您需要使用join field来建立它。为了能够使用子记录进行排序,您需要能够将排序关键字表示为单个浮点数,并将其用作here解释的得分。
不过现在有免费的午餐,这种设置会比普通搜索慢,所以你在某种程度上是在用搜索性能来换取减少的索引负载。也就是说,40 k文档并不是一个很大的索引,所以我希望它能够轻松地处理增长。

3yhwsihp

3yhwsihp2#

AFAIK,update在Elasticsearch中是昂贵的(追加新文档,标记旧文档已删除)。
我认为你可以尝试append(就像插入,而不是update)你的计数器的新状态,如likesdownloads与时间戳。
不确定你的数据。
它可以是累积状态,也可以是每个字段的单独事件。
例如,累积状态(仅为演示而删除引号):

# document 1
{
  @timestamp: T1,
  likes: 180,
  downloads: 10000 
}

# document 2
{
  @timestamp: T2,
  likes: 181,
  downloads: 10100 
}

# then do subtracts with painless or your backend program to get diff in a given time range.

# consider delete old data by _delete_by_query depends on your need; since old accumulated status maybe useless.

或分离事件

# document 1
{
  @timestamp: T1,
  likes: 0,
  downloads: 4 
}

# document 2
{
  @timestamp: T2,
  likes: 1,
  downloads: 10
}

# do some agg (aggregation) later.

这样,如果数据每分钟只有几百个,append应该没问题。
我更喜欢分开的,因为稍后执行agg更容易显示我想要的内容。

相关问题