基于代价的优化器

当 Manticore 执行全扫描查询时,它可以使用普通扫描检查每个文档是否符合过滤条件,或者采用额外的数据和/或算法来加快查询执行速度。Manticore 使用基于代价的优化器(CBO),也称为“查询优化器”,来确定采用哪种方式。

CBO 还可以提升全文查询的性能。详见下文。

如果 CBO 判断某些措施能够提升性能,它可能决定将一个或多个查询过滤器替换为以下实体之一:

  1. docid 索引 利用一种特殊的仅包含 docid 的二级索引,存储在扩展名为 .spt 的文件中。除了提升文档 ID 过滤器的性能外,docid 索引还用于加速文档 ID 到行 ID 的查找,并加快守护进程启动时大量 killlist 的应用。
  2. 列式扫描 依赖于列式存储,只能用于列式属性。它扫描每个值并对其应用过滤器,但进行了高度优化,通常比默认方法更快。
  3. 二级索引 默认为所有属性(除 JSON 外)生成。它们使用 PGM 索引 以及 Manticore 内置的倒排索引来检索对应某个值或值范围的行 ID 列表。二级索引存储在扩展名为 .spidx.spjidx 的文件中。 有关如何为 JSON 属性生成二级索引的信息,请参见 json_secondary_indexes

优化器利用各种属性统计信息估算每条执行路径的代价,包括:

  1. 关于属性内数据分布的信息(直方图,存储在 .sphi 文件中)。直方图在数据建立索引时自动生成,是 CBO 的主要信息来源。
  2. PGM(二级索引)信息,有助于估算需要读取的文档列表数量。这有助于评估文档列表合并性能及选择合适的合并算法(优先队列合并或位图合并)。
  3. 列式编码统计数据,用于估算列式数据解压性能。
  4. 列式最小-最大树。CBO 使用直方图估算应用过滤器后剩余的文档数,同时需要确定过滤器处理过的文档数。对于列式属性,部分评估最小-最大树用于此目的。
  5. 全文字典。CBO 利用词项统计信息估算全文树评估代价。

优化器计算查询中每个过滤器的执行代价。由于某些过滤器可以被多种实体替代(例如,对于文档 ID,Manticore 可用普通扫描、docid 索引查找、列式扫描(如果文档 ID 是列式的)以及二级索引),优化器会评估所有可用组合。但组合数最大限制为 1024。

为估算查询执行代价,优化器计算执行查询时所执行的最重要操作的预估代价。它采用预设常数代表每个操作的代价。

优化器对比各执行路径的代价,选择代价最低的路径以执行查询。

当处理带有属性过滤器的全文查询时,查询优化器在两条可能的执行路径间做出决定。一种是执行全文查询,获取匹配结果并应用过滤器;另一种是用上述一个或多个实体替换过滤器,从中获取行 ID 并注入全文匹配树。这样,全文搜索结果会与全扫描结果取交集。查询优化器估算全文树评估成本和计算过滤器结果的最佳路径,利用这些信息选择执行路径。

另一个考虑因素是多线程查询执行(当启用 pseudo_sharding 时)。CBO 意识到某些查询可并发执行,并将其纳入考量。CBO 优先考虑更短的查询执行时间(即延迟)胜过吞吐量。例如,如果使用列式扫描的查询能在多线程(占用多个 CPU 核心)中执行,且比单线程使用二级索引的查询更快,则优先多线程执行。

使用二级索引和 docid 索引的查询始终单线程执行,因为基准测试表明它们多线程执行几乎无益。

目前,优化器仅考虑 CPU 代价,不考虑内存或磁盘使用。

Last modified: August 28, 2025