查询
Quickwit 提供了两个带有全文搜索查询的端点,这些查询由 query
参数标识:
搜索器接收到的搜索查询将按照以下步骤使用 Map-Reduce 方法执行:
- 搜索器根据请求的时间戳区间(参见[时间分片])和标签(参见[标签剪枝])来确定相关的分片。
- 它使用 rendez-vous 哈希 在集群中的其他可用搜索器之间分发分片工作负载,以优化缓存和负载。
- 最后,它等待所有结果,合并它们,并将结果返回给客户端。
搜索流查询遵循与搜索查询相同的执行路径,除了最后一步:而不是等待每个搜索器的结果,搜索器一旦开始从某个搜索器接收结果就立即流式传输这些结果。
Time sharding(时间分片)
对于具有时间成分的数据集,Quickwit 将数据分片为具有时间戳感知的分片。借助此功能,Quickwit 能够在查询处理阶段之前过滤掉大部分分片,从而大幅减少处理查询所需的数据量。
以下查询参数可用于对您的查询应用时间戳剪枝:
startTimestamp
: 限制搜索范围为具有timestamp >= start_timestamp
的文档endTimestamp
: 限制搜索范围为具有timestamp < end_timestamp
的文档
Tag pruning(标签剪枝)
Quickwit 还提供了在第二个维度上进行剪枝的功能,这个维度被称为 tags
。通过 将字段设置为带标签,Quickwit 将在索引时生成分片元数据,以便在查询时过 滤出匹配请求标签的分片。请注意,这种元数据仅在字段基数小于 1,000 时生成。
标签剪枝在多租户数据集中特别有用。
Partitioning(分区)
Quickwit 可以根据分区键将文档路由到不同的分片中。
此功能尤其适用于不同标签的文档混合在同一来源(通常是 Kafka 主题)的情况。
在这种情况下,仅仅将字段标记为标签对搜索没有积极影响,因为所有产生的分片几乎都包含所有标签。
partition_key
属性(在文档映射中定义)允许您配置 Quickwit 用来将文档路由到隔离分片的逻辑。
Quickwit 在合并过程中也会强制执行这种隔离。从某种意义上说,此功能类似于分片。
分区和标签经常用于:
- 在多租户应用程序中分离
tenants
- 在观察日志情况下分离
team
或application
生成大量分片可能会给 indexer
带来巨大压力。因此,
文档映射中的另一个参数 max_num_partitions
作为安全阀。如果分区数量接近超过 max_num_partitions
,则创建一个额外的分区,
并将所有额外分区组合到这个特殊分区中。
如果您期望有 20 个分区,我们强烈建议您不要将 max_num_partitions
设置为 20,而是使用一个较大的值(例如 200)。
Quickwit 应该能够平稳地处理这么多分区的数量,并且可以避免由于少数错误的文档而导致属于不同分区的文档被组合在一起。
分区键 DSL
Quickwit 允许您使用简单的 DSL 配置文档的路由方式。以下是一些示例表达式及其结果的简短描述:
tenant_id
: 每个tenant_id
创建一个分区tenant_id,app_id
: 每个tenant_id
和app_id
的唯一组合创建一个分区tenant_id,hash_mod(app_id, 8)
: 对于每个租户,最多创建 8 个分区,每个分区包含一些应用程序的相关数据hash_mod((tenant_id,app_id), 50)
: 总共创建 50 个分区,其中包含一些租户和应用程序的组合。
分区键 DSL 由以下语法生成:
RoutingExpr := RoutingSubExpr [ , RoutingExpr ]
RougingSubExpr := Identifier [ \( Arguments \) ]
Identifier := FieldChar [ Identifier ]
FieldChar := { a..z | A..Z | 0..9 | _ }
Arguments := Argument [ , Arguments ]
Argument := { \( RoutingExpr \) | RoutingSubExpr | DirectValue }
# We may want other DirectValue in the future
DirectValue := Number
Number := { 0..9 } [ Number ]
目前支持的函数包括:
hash_mod(RoutingExpr, Number)
: 对RoutingExpr
进行哈希运算,并将结果除以Number
,只保留余数。
当使用 hash_mod
与键元组(如 hash_mod((tenant_id,app_id), 50)
)时,请注意这可能会将文档路由到一起,从而使标签效果降低。
例如,如果 tenant_1,app_1 和 tenant_2,app_2 都被发送到第 1 个分区,而 tenant_1,app_2 被发送到第 2 个分区,则对 tenant_1,app_2 的查询
仍然会在第 1 个分区中搜索,因为它会被标记为 tenant_1,tenant_2,app_1 和 app_2。因此,您应该更倾向于使用像
hash_mod(tenant_id, 10),hash_mod(app_id, 5)
这样的分区键,这样会生成同样数量的分片,但具有更好的标签。
搜索流查询限制
搜索流查询可能占用大量的 RAM。Quickwit 默认将每个分片的并发搜索流数量限制为 100。您可以通过设置搜索器配置文件中名为 max_num_concurrent_split_streams
的属性值来调整此限制。
Caching(缓存)
Quickwit 在许多地方使用缓存以实现高性能的查询引擎。
- Hotcache 缓存:一种静态缓存,用于存储关于分片文件内部表示的信息。它有助于加快打开分片文件的速度。其大小可通过
split_footer_cache_capacity
配置参数定义。 - 快速字段缓存:快速字段通常被用户频繁访问,尤其是在流请求中。它们被缓存在 RAM 中,其大小可以通过
fast_field_cache_capacity
配置值限制。 - 部分请求缓存:在某些情况下,例如使用仪表板时,可能会发出非常相似的请求,只有时间戳边界发生变化。可以缓存一些部分结果以使这些请求更快并减少向存储发出的请求。它们被缓存在 RAM 中,其大小可以通过
partial_request_cache_capacity
配置值限制。
Scoring(排序)
Quickwit 支持按 BM25 分数对文档进行排序。为了按分数查询,必须为字段启用 fieldnorms。默认情况下,BM25 排序处于禁用状态以提高查询延迟,但可以通过在查询中将 sort_by
选项设置为 _score
来启用。