ElasticSearch-查询性能的路由与索引

3vpjnl9f  于 2023-02-07  发布在  ElasticSearch
关注(0)|答案(3)|浏览(159)

我正在计划一个策略,用于按日期和用户方向查询数百万个文档。

  • 选项1 -按用户索引。按日期路由。
  • 选项2 -按日期编制索引。按用户路由。

使用布线或索引有什么区别或优点?

tvokkenx

tvokkenx1#

Shay Banon @ Elasticsearch recommends的设计模式之一是:按时间范围索引按用户路由并使用别名
为每一天(或一个日期范围)创建一个索引,并在user字段上路由文档,这样您就可以“退休”旧日志,并且不需要在所有碎片上执行查询:

$ curl -XPOST localhost:9200/user_logs_20140418 -d '{
    "mappings" : {
        "user_log" : {
            "_routing": {
              "required": true,
              "path": "user"
            },
            "properties" : {
              "user" : { "type" : "string" },
              "log_time": { "type": "date" }
            }
        }
    }
}'

创建一个alias来过滤和route用户,这样您就可以查询user_foo的文档:

$ curl -XPOST localhost:9200/_aliases -d '{
  "actions": [{
    "add": {
      "alias": "user_foo",
      "filter": {"term": {"user": "foo"}},
      "routing": "foo"
    }
  }]
}'

为时间窗口创建别名,以便可以查询文档this_week

$ curl -XPOST localhost:9200/_aliases -d '{
  "actions": [{
    "add": {
      "index": ["user_logs_20140418", "user_logs_20140417", "user_logs_20140416", "user_logs_20140415", "user_logs_20140414"],
      "alias": "this_week"
    }, 
    "remove": {
      "index": ["user_logs_20140413", "user_logs_20140412", "user_logs_20140411", "user_logs_20140410", "user_logs_20140409", "user_logs_20140408", "user_logs_20140407"],
      "alias": "this_week"
    }
  }]
}'

这种方法的一些优点是:

  • 如果使用别名搜索用户,则只会命中用户数据所在的碎片
  • 如果用户的数据增长,您可以考虑为该用户创建单独的索引(您所需要的只是将该用户的别名指向新索引)
  • 对碎片分配没有性能影响
  • 您可以通过简单地关闭(当您关闭索引时,它们实际上不消耗任何资源)或删除整个索引(删除索引比删除索引中的文档简单)来“淘汰”旧日志
8aqjt8rx

8aqjt8rx2#

索引是解析你索引过的文档的过程,就像一本教科书的附录。
当索引数据超过一个服务器限制时,请添加另一个服务器并与它们共享数据,而不是升级服务器配置。此过程称为分片
如果我们搜索,它将在所有碎片中搜索,并执行map reduce和返回结果。如果我们将相似的数据分组在一起,并在特定数据中搜索一些数据,这意味着它降低了处理能力,提高了速度。

路由用于将数据组存储在特定碎片中。选择路由字段。该字段应存在于所有文档中,字段不应包含不同的值。
注意:路由应该在多个分片环境中使用[而不是在单个节点中]。如果我们在单个节点中使用路由。则没有使用它。

kpbwa7wx

kpbwa7wx3#

让我们先定义一下术语。

索引在Elasticsearch的上下文中可以表示许多含义:
*为文档编制索引:向Elasticsearch写入新文档
*索引字段:将Map(方案)中的字段定义为已索引。需要对搜索的所有字段进行索引(默认情况下,对所有字段进行索引)
*ElasticSearch索引:这是一个配置单元(例如模式/Map)和数据单元(例如磁盘上的一些文件)。从文档被写入索引的意义上说,它类似于数据库。当你搜索时,你可以访问一个或多个索引
*Lucene索引:一个Elasticsearch索引可以被分成N个碎片。2一个碎片就是一个Lucene索引。3当你索引一个文档时,这个文档被路由到其中一个碎片。4当你在索引中搜索时,搜索被广播到每个碎片的副本。5每个碎片用它所知道的内容回复,然后结果被聚合并发送回客户端

根据上下文判断,“按用户索引”和“按日期索引”指的是每个用户一个索引或每个日期间隔(例如天)一个索引。

Routing指的是将文档发送到shards,正如我前面所描述的,默认情况下,这是随机完成的:散列范围除以碎片的数量,当一个文档进入时,Elasticsearch散列它的_id,散列福尔斯其中一个碎片的散列范围==〉,这就是文档要去的地方。

您可以使用自定义路由对此进行控制:Elasticsearch可以散列一个路由值(例如用户名),而不是散列_id。因此,具有相同路由值(即相同用户)的所有文档都位于同一个碎片上。然后,可以在查询时使用路由,以便Elasticsearch只查询一个碎片(每个索引),而不是N个。这可以带来massive query performance gains(请特别查看幻灯片24)。
回到手头的问题,我认为“当按索引或使用路由分解数据时有什么区别或优势?”
为了回答这个问题,该战略应考虑到:

*如何建立索引建立索引(写入).如果建立索引的工作量很大,则需要确保所有节点都参与(即在相同数量的碎片上写入类似数量的数据),否则将出现瓶颈
*如何查询数据.如果查询经常引用单个用户的数据,那么将数据按用户细分(按用户索引或按用户路由)是很有用的
*碎片总数。碎片、节点和字段越多,群集状态就越大。如果群集状态的大小变大(例如,大于数十MB),就很难在所有节点上保持同步,从而导致群集不稳定。根据经验,您希望单个Elasticsearch群集中的碎片数量保持在数千个碎片中的数十个以内

在实践中,我看到了以下设计:
1.每个固定时间间隔一个索引。您将在日志中看到这一点(例如,默认情况下Logstash写入每日索引)
1.每个时间间隔一个索引,按大小循环。这样即使写入吞吐量变化,索引大小也保持不变
1.每个用户一个索引“series”(1.或2.)。如果用户很少,这很好用,因为它消除了过滤。但是如果用户很多,它就不起作用了,因为你有太多的碎片
1.每个时间间隔一个索引(1.或2.),有大量的碎片,并按用户路由。如果用户很多,这很好用。正如Mahesh指出的,如果一些用户有大量数据,就会出现问题,导致碎片不均匀。在这种情况下,需要一种方法将大用户reindex到他们自己的索引中(参见3.),并且可以使用别名向应用程序隐藏此逻辑。
我还没有看到每个用户一个索引和按日期间隔路由的设计。这里的主要缺点是您可能***一次写入一个碎片***(包含今天哈希的碎片)。这将限制您的写入吞吐量和平衡写入的能力。但这种设计可能适用于大量但不是很大的用户(例如1 K),在有限的时间间隔内写入很少,查询很多。
顺便说一句,如果你想了解更多这方面的东西,我们有一个Elasticsearch Operations training,在那里我们讨论了很多关于架构,权衡,ElasticSearch如何在引擎盖下工作。我讲授这门课)

相关问题