blog-post

Manticore Search 索引和文档存储

从 v 3.2.0 开始,Manticore Search 引入了一项新特性 - 文档存储。

历史上,Manticore Search 是一个文本搜索引擎,它索引文本但不保留原始文本。文本经过处理,从简单的字符串转变为特殊结构,形成全文索引,从而允许快速文本搜索。在结果集中,用户无法获得原始文本,因为从全文索引中重组它可能是一个复杂的过程。此外,索引设置可能包括一些停止特定单词被索引的条款(如最小单词长度或停用词),这可能使重构变得不可能。

搜索工作流程是为了在 Manticore 中执行全文搜索而创建的,并基于结果集在原始数据源(数据库或文件)中执行额外查找,以检索仅索引在 Manticore 中的内容。在某些情况下,额外查找是必需的,以检索不仅是“缺失”的文本,还有其他未包含在索引中的数据,因为这些数据在搜索操作中未使用,这样的数据只会(不必要地)增加索引大小。但在很多情况下,查找的唯一目的是获取“缺失”的文本,这被视为一个额外的步骤,最好消除——因为它意味着简化应用程序代码,避免额外的负载、资源消耗和数据存储中的另一个故障点。

还有一些场景,其中原始数据并不驻留在传统的数据库中,并且在查询时从数据中检索原始文本可能会很慢。要求将这些数据存储在数据库中可以被视为不必要的,作为使用数据库的唯一理由,以弥补搜索引擎不能存储原始内容的能力。这些场景可能是:

  • 一家公司可能希望能够搜索办公室文档中的文本,如 Word 或 PDF - 这些可以是内部工具的一部分或提供科学、法律或技术论文的门户。
  • 数据来自网络服务或抓取的页面
  • 流数据,可以是日志、消息或电子邮件。从源读取这些数据可能很困难,因为在很多情况下,它们存储在分布式系统中,而在查询时读取它们会使应用程序代码变得复杂

您可以通过我们的 交互式课程 学习如何不仅执行索引操作,还存储文档内容。

现在可以存储原始文本并在结果中检索回来。

我们应该提到,DS 特性并没有使 Manticore 成为一个传统的数据库。Manticore支持事务及 binlog 恢复,尽管它提供了大多数 ACID 属性,但不被视为真正的 ACID 兼容数据库。

此时存储也没有加密。敏感或关键数据,如用户凭据或支付交易,不视为适合存储在 Manticore 中。此外,传统数据库的一些特性,如 JOINs,目前仍不支持。但我们会在未来版本中对此进行改进。

不过,在许多情况下,仅仅使用 Manticore 来存储数据或存储而不进行额外查找是非常有意义的。

文档存储可以减少对原始数据仓库的工作负载或减少空间要求。
在撰写本文时,文档存储的性能也是一个方面。但我们预计在下一版中将大大改善这一方面。

使用方法

可以使用 stored_fields 索引指令启用存储,它接受由逗号分隔的字段名称列表。

index myindex {
   type     = rt
   path     = /path/to/myindex
   rt_field  = title
   rt_field = short_description
   rt_field = long_description
   rt_attr_string = title
   rt_attr_uint   = group_id
   stored_fields  = short_description, long_description
}

如果没有存储字段,结果将呈现如下:

mysql> SELECT * FROM myindex WHERE ....\G
*************************** 1. row ***************************
      id: 11
   title: A title goes here
group_id:100
*************************** 2. row ***************************
...

有了存储字段:

mysql> SELECT * FROM myindex WHERE ....\G
*************************** 1. row ***************************
               id: 11
            title: A title goes here
short_description: A short text description
goes here
 long_description: A long text description
can be found here
         group_id:100
*************************** 2. row ***************************
...

带有和不带有文档存储的索引展示可以在我们的 docstore 课程 中查看。

高级调优

文本存储在磁盘上的一个单独文件中。默认情况下,它们使用 lz4 算法进行压缩。可用替代 lz4hc 算法,或者通过设置 ‘docstore_compression’ 索引指令来禁用压缩(“none”)。对于 ’lz4hc’ 算法,可以通过 docstore_compression_level 索引指令调整压缩级别,该值范围为 1 到 12(默认值为 9)。文本以块的形式在磁盘上进行压缩。块大小可以通过 docstore_block_size 指令进行调整。默认值为 16k。增加块大小将改善压缩比并节省更多磁盘空间,而减小块大小应改善访问速度。

当搜索需要从存储中提取文本时,包含它的块会从磁盘读取并解压缩。由于一个块可能包含来自多个文档的文本,因此解压缩的块可以缓存到内存中。默认情况下,使用的是全守护进程的 16MB 缓存。缓存大小可以通过 searchd 的 docstore_cache_size 设置进行调整。

与字符串属性的差异

Manticore Search 已经引入了一种 数据类型 ,能够在结果集中存储和检索文本,并且还可以用于比较、正则过滤、排序和聚合操作。更重要的是,在实时索引的情况下,可以为全文字段和字符串属性使用相同的名称。关于存储字段的目的,有一个问题。

字符串属性存储在 Manticore Search 3 索引的 blob 组件中,该组件还包含 JSON 和 MVA 属性。从 blob 组件读取数据是通过 mmap() 管理的,可以留在磁盘上并根据需要读取,或者在索引加载时完全读取和加载,或者在内存中读取、加载和锁定。字符串属性中的文本以未压缩的形式存储。如果以这种方式存储的文本较长(如描述、文章内容),它们可能会占用大量磁盘空间,并将增加文档的 blob 组件所使用的内存。对于之前未能完全适配 RAM 的索引,将长文本作为字符串属性添加到其中意味着 更少 的可变长度属性(字符串、JSON、MVA)可以缓存到 RAM 中,从而导致性能不如预期。锁定 blob 组件到内存中 (access_blob_attrs=mlock) 可能因为尺寸增大而变得不可行。字符串属性应当用于简短文本,预计对其进行非全文过滤、分组和排序操作,而不仅仅是检索。

另一方面,存储字段是一个独立的组件。文本仅从磁盘读取,如果有可用的 RAM,可以将 docstore_cache_size 设置为较高的值(GB)来在 RAM 中缓存存储字段。此外,默认情况下,存储字段是压缩的,使用的存储空间少于字符串属性。还有一些情况下,文本需要存储在索引中,并且仅在输出时使用,完全不用于过滤/排序/分组。从资源管理的角度来看,将它们放在 blob 中并不是最佳选择。此类字符串的示例可以是产品代码或 UUID(这些应该是唯一的,对其进行排序并没有太大意义)。将它们移到存储字段将使 blob 变小,意味着使用的 RAM 较少,启动时加载更快,并且根据情况,允许 mlocking。这里可能出现的一个“问题”是,新的字段可能在执行不搜索特定字段的全文匹配时发挥作用,因此使用 ignore field search operator 来将其排除在搜索之外可能是个好主意。

安装Manticore Search

安装Manticore Search