Link Search Menu Expand Document Documentation Menu

时间点

时间点 (PIT) 让您可以针对固定时间点的数据集运行不同的查询。

通常,如果您对同一个索引多次运行查询,由于文档会持续索引、更新和删除,相同的查询可能会返回不同的结果。如果您需要针对相同数据运行查询,可以通过创建 PIT 来保留数据的状态。PIT 功能的主要用途是将其与 search_after 功能结合使用,以实现搜索结果的深度分页。

搜索结果分页

除了 PIT 功能之外,OpenSearch 中还有三种方法可以对搜索结果进行分页:使用 Scroll API、为搜索指定 fromsize 参数,以及使用 search_after 功能。然而,这三种方法都有局限性。

  • Scroll API 的搜索结果在请求发出时被冻结,但它们绑定到特定的查询。此外,滚动只能向前移动搜索,因此如果某个页面的请求失败,后续请求会跳过该页面并返回下一页。
  • 如果为搜索指定 fromsize 参数,搜索结果不会在时间上冻结,因此它们可能由于文档被索引或删除而导致不一致。fromsize 功能不建议用于深度分页,因为每个页面请求都需要处理所有结果并为请求的页面进行筛选。
  • search_after 搜索结果不会在时间上冻结,因此它们可能由于并发文档索引或删除而导致不一致。

PIT 功能没有其他分页方法的局限性,因为 PIT 搜索不绑定到查询,并且支持向前和向后的一致分页。如果您查看了结果的第一页,现在在第二页,如果您返回,您将看到相同的原始第一页。

PIT 搜索与常规搜索具有相同的功能,不同之处在于 PIT 搜索作用于较旧的数据集,而常规搜索作用于实时数据集。PIT 搜索不绑定到查询,因此您可以对时间冻结的同一数据集运行不同的查询。

您可以使用 Create PIT API 来创建 PIT。当您为一组索引创建 PIT 时,OpenSearch 会锁定这些索引的一组段,将其冻结在时间中。在较低级别,此 PIT 所需的任何资源都不会被修改或删除。如果作为 PIT 一部分的段被合并,OpenSearch 会在 PIT 创建时由 keep_alive 参数指定的时间段内保留这些段的副本。

创建 PIT 操作会返回一个 PIT ID,您可以使用该 ID 对冻结的数据集运行多个查询。即使索引继续摄取数据并修改或删除文档,PIT 仍然引用自 PIT 创建以来未更改的数据。当您的查询包含 PIT ID 时,您无需将索引传递给搜索,因为它会使用该 PIT。带有 PIT ID 的搜索在多次运行时会产生完全相同的结果。

在集群或节点故障的情况下,所有 PIT 数据都将丢失。

SQL 中的 PIT

SQL 插件也支持使用 PIT 进行分页。当 plugin.sql.pagination.api 设置启用时(默认),OpenSearch 中的 SQL 搜索查询会自动在内部使用 PIT。有关更多信息,请参阅 SQL 中的分页

使用 PIT 和 search_after 分页

当您使用 PIT ID 运行查询时,可以使用 search_after 参数检索下一页结果。这让您可以控制结果页面中文档的顺序。

使用 PIT ID 运行搜索查询

GET /_search
{
  "size": 10000,
  "query": {
    "match" : {
      "user.id" : "elkbee"
    }
  },
  "pit": {
    "id":  "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==", 
    "keep_alive": "100m"
  },
  "sort": [ 
    {"@timestamp": {"order": "asc"}}
  ]
}

响应包含与查询匹配的前 10,000 个文档。要获取下一组文档,请运行相同的查询,将最后一个文档的排序值作为 search_after 参数,并保持相同的 sortpit.id。您可以使用可选的 keep_alive 参数来延长 PIT 时间。

GET /_search
{
  "size": 10000,
  "query": {
    "match" : {
      "user.id" : "elkbee"
    }
  },
  "pit": {
    "id":  "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==", 
    "keep_alive": "100m"
  },
  "sort": [ 
    {"@timestamp": {"order": "asc"}}
  ],
  "search_after": [  
    "2021-05-20T05:30:04.832Z"
  ]
}

搜索分片

search_after 与 PIT 结合用于分页,可以控制结果的顺序。如果您不需要特定顺序的结果,或者如果您希望能够从一个页面跳到非连续页面,则可以使用搜索分片。搜索分片将 PIT 搜索拆分为多个切片,客户端应用程序可以独立地使用这些切片。

例如,如果您有一个 PIT 搜索查询,它有 1,000,000 个结果,并且您想一次返回 50,000 个结果,您的客户端应用程序必须进行 20 次连续调用才能接收每批结果。如果您使用搜索分片,您可以并行化这 20 个调用。在您的多线程客户端应用程序中,您可以为每个 PIT 使用五个切片。结果是,您将有 5 个 10,000 次命中的切片,可以由客户端中的五个不同线程使用,而不是由单个线程使用 50,000 个结果。

要使用搜索分片,您必须指定两个参数

  • slice.id 是您请求的切片 ID。
  • slice.max 是将搜索响应拆分为的切片数量。

以下 PIT 搜索查询演示了搜索分片


GET /_search
{
  "slice": {
    "id": 0,  // id is the slice (page) number being requested. In every request we can only query for one slice                    
    "max": 2  // max is the total number of slices (pages) the search response will be broken down into                  
  },
  "query": {
    "match": {
      "message": "foo"
    }
  },
  "pit": {
    "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
  }
}

在每个请求中,您只能查询一个切片,因此下一个查询将与上一个查询相同,只是 slice.id 将是 1

API

下表列出了所有 时间点 API 函数。

功能 API 描述
创建 PIT POST /<目标索引>/_search/point_in_time?keep_alive=1h 创建 PIT。
列出 PIT GET /_search/point_in_time/_all 列出所有 PIT。
删除 PIT DELETE /_search/point_in_time
DELETE /_search/point_in_time/_all
删除一个或所有 PIT。
CAT PIT 分段 GET /_cat/pit_segments/_all 通过描述其 Lucene 段来提供有关 PIT 磁盘利用率的信息。

有关所需权限,请参阅 安全模型

PIT 设置

您可以为 PIT 指定以下设置。

设置 描述 默认值
point_in_time.max_keep_alive 一个集群级设置,指定 keep_alive 参数的最大值。 24小时
search.max_open_pit_context 一个节点级设置,指定节点上开放 PIT 上下文的最大数量。 300
剩余 350 字符

有问题?

想贡献?