时间点查询

时间点查询允许您对某个时间点上固定的数据集运行不同的查询。通常,如果您在同一个索引上多次运行查询,相同的查询可能会返回不同的结果,因为文档会持续地被索引、更新和删除。如果您需要对相同的数据运行查询,可以通过创建时间点查询来保存该数据的状态。时间点查询功能的主要用途是将其与 search_after 功能结合,实现搜索结果的分页浏览。

搜索结果分页

除了时间点查询功能外,UDB-SX 中还有三种对搜索结果分页的方法:使用滚动 API、为搜索指定 fromsize 参数,以及使用 search_after 功能。但这三种方法都有局限性:

  • 滚动 API 的搜索结果在请求时被冻结,但它们与特定查询绑定。此外,滚动只能向前移动,因此如果一个分页请求失败,后续请求将跳过该页并返回下一页。

  • 如果为搜索指定 fromsize 参数,搜索结果不会在时间点上冻结,因此可能由于文档被索引或删除而导致不一致。不推荐将 fromsize 功能用于深度分页,因为每个分页请求都需要处理所有结果,并为请求的页面进行筛选。

  • search_after 的搜索结果不会在时间点上冻结,因此可能由于并发文档索引或删除而导致不一致。

时间点查询功能没有其他分页方法的局限性,因为时间点查询不绑定于特定查询,并且支持前后一致的分页。如果您查看了结果的第一页,现在在第二页,那么当您返回第一页时,您将看到相同的第一页。

时间点查询搜索

时间点查询搜索具有与常规搜索相同的功能,区别在于时间点查询搜索作用于一个较旧的数据集,而常规搜索作用于实时数据集。时间点查询搜索不绑定于特定查询,因此您可以在同一个在时间点上冻结的数据集上运行不同的查询。

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

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

如果发生集群或节点故障,所有时间点查询数据都将丢失。

SQL 中的时间点查询

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

使用时间点查询和 search_after 进行分页

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

使用时间点查询 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 参数来延长时间点查询的时间:

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 与时间点查询结合用于分页,您可以控制结果的顺序。如果不需要结果按任何特定顺序排列,或者希望能够从一页跳转到非连续的页面,您可以使用搜索切片。搜索切片将时间点查询搜索拆分为多个切片,客户端应用程序可以独立使用这些切片。

例如,如果您有一个时间点查询搜索查询,有 1,000,000 个结果,并且您希望每次返回 50,000 个结果,那么您的客户端应用程序需要连续进行 20 次调用才能接收每批结果。如果您使用搜索切片,您可以并行处理这 20 次调用。在您的多线程客户端应用程序中,您可以为每个时间点查询使用五个切片。结果,您将得到 5 个 10,000 条结果的切片,可以由客户端中的五个不同线程使用,而不是让单个线程处理 50,000 条结果。

要使用搜索切片,您需要指定两个参数:

  • slice.id 是您请求的切片 ID。

  • slice.max 是要将搜索结果拆分成的切片数量。

以下时间点查询搜索查询说明了搜索切片的使用:

GET /_search
{
  "slice": {
    "id": 0,  // id 是正在请求的切片(页)编号。在每个请求中,我们只能查询一个切片                    
    "max": 2  // max 是搜索结果将被拆分成的切片(页)总数                  
  },
  "query": {
    "match": {
      "message": "foo"
    }
  },
  "pit": {
    "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
  }
}

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

安全模型

如果您在启用了安全插件的情况下运行 UDB-SX,本节描述使用时间点查询 API 操作所需的权限。

用户可以使用 point_in_time_full_access 角色访问所有时间点查询 API 操作。如果此角色不符合您的需求,可以混合匹配单个时间点查询权限以满足您的用例。每个操作对应 REST API 中的一个操作。例如,indices:data/read/point_in_time/create 权限允许您创建时间点查询。以下是可能的权限:

  • indices:data/read/point_in_time/create – 创建 API

  • indices:data/read/point_in_time/delete – 删除 API

  • indices:data/read/point_in_time/readall – 列出所有时间点查询 API

  • indices:data/read/search – 搜索 API

  • indices:monitor/point_in_time/segments – 时间点查询段 API

对于所有 API 操作,例如列出所有和删除所有,用户需要所有索引(*)的权限。对于诸如搜索、创建时间点查询或删除列表等 API 操作,用户只需要单个索引的权限。

时间点查询 ID 在保存时总是包含底层(已解析的)索引。以下各节描述别名和数据流所需的权限。

别名权限

对于别名,用户必须对任何时间点查询操作拥有索引别名权限。

数据流权限

对于数据流,用户必须对任何时间点查询操作同时拥有数据流以及数据流的后备索引的权限。例如,用户必须拥有 data-stream-11 数据流及其后备索引 .ds-my-data-stream11-000001 的权限。

如果用户只有数据流权限,他们将能够创建时间点查询,但如果没有后备索引权限,他们将无法使用时间点查询 ID 进行其他操作,例如搜索。

API

下表列出了所有时间点查询 API 功能。

功能 API 描述
创建时间点查询 POST /<target_indexes>/_search/point_in_time?keep_alive=1h 创建时间点查询。
列出时间点查询 GET /_search/point_in_time/_all 列出所有时间点查询。
删除时间点查询 DELETE /_search/point_in_time
DELETE /_search/point_in_time/_all
删除时间点查询或所有时间点查询。
时间点查询段 GET /_cat/pit_segments/_all 通过描述其 Lucene 段,提供有关时间点查询磁盘使用情况的信息。

有关相关集群和节点设置的信息,请参阅时间点查询设置