# Manticore Search Indexes and document storage

## 从 v 3.2.0 版本开始，Manticore Search 引入了一个新功能 - 文档存储。

历史上，Manticore Search 是一个文本搜索引擎，它对文本进行索引但不保留原始内容。文本经过处理，从普通字符串转换为特殊结构，这些结构构成全文索引，从而实现快速文本搜索。在结果集中，用户不会接收到原始文本，因为从全文索引中重新组合文本可能是一个复杂的过程。此外，索引设置可能包含阻止某些单词被索引的条款（如最小单词长度或停用词），这可能会使重建变得不可能。

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

还有一些场景中，原始数据并不存储在传统数据库中，在查询时从数据中检索原始文本可能会很慢。要求将这些数据存储在数据库中可能被视为不希望的，且使用数据库的唯一原因是为了弥补搜索引擎无法存储原始内容的不足。这些场景可能包括：

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

你可以通过我们的 [交互课程](https://play.manticoresearch.com/docstore/) 学习如何不仅使用索引，还存储文档内容。


## 现在可以存储原始文本并在结果中检索它们。

我们应指出，DS 功能不会使 Manticore 成为传统数据库。Manticore 支持事务和 binlog 恢复，尽管它提供了大多数 ACID 属性，但不被视为真正的 ACID 合规数据库。

目前存储也没有加密。敏感或关键数据，如用户凭证或支付交易，不被视为适合存储在 Manticore 中。此外，传统数据库的一些功能，如 JOIN，尚未得到支持。但我们将在未来的版本中对此进行改进。


### **然而，有很多情况下仅使用 Manticore 来存储数据或存储而不进行额外查找是有意义的。**


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


#### 使用方法

可以通过使用 stored_fields 索引指令启用存储，该指令接受以逗号分隔的字段名称列表。

```sql
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
}
```

如果没有存储字段，结果会像这样：

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

```

有存储字段时：

```sql
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 课程](https://play.manticoresearch.com/docstore/) 中可以查看带有和不带文档存储的索引之间的对比。


#### 高级调优

文本存储在磁盘上的单独文件中。默认情况下，它们使用 lz4 算法进行压缩。还可以使用 lz4hc 算法或通过设置 'docstore_compression' 索引指令来禁用压缩（'none'）。对于 'lz4hc' 算法，可以通过 docstore_compression_level 索引指令调整压缩级别，该指令可以取 1 到 12 的值（默认值为 9）。文本在磁盘上以块的形式压缩。块大小可以通过 docstore_block_size 指令进行调整。默认值为 16k。增加块大小将提高压缩率并节省更多磁盘空间，而减小块大小应提高访问速度。

当搜索需要从存储中获取文本时，包含该文本的块将从磁盘读取并解压缩。由于一个块可能包含多个文档的文本，解压缩的块可以缓存在内存中。默认情况下，使用一个 16MB 的守护进程范围缓存。可以通过 searchd 的 docstore_cache_size 设置调整缓存大小。

#### 与字符串属性的区别


Manticore Search 已经具备一种 [数据类型](https://docs.manticoresearch.com/latest/html/indexing/data_types.html#string)，能够存储并在结果集中检索文本，还可以用于比较、正则表达式过滤、排序和聚合操作。此外，对于实时索引，可以使用相同的名称来表示全文字段和字符串属性。那么存储字段的用途是什么呢？

字符串属性存储在 Manticore Search 3 索引的 blob 组件中，该组件还包含 JSON 和 MVA 属性。对 blob 组件的读取通过 [mmap()](https://docs.manticoresearch.com/latest/html/conf_options_reference/searchd_program_configuration_options.html#access-blob-attrs) 管理，可以保留在磁盘上并根据需要读取，或者在索引加载时完全读取和加载，或者读取、加载并锁定在内存中。字符串属性中的文本以未压缩的形式存储。如果以这种方式存储的文本很长（如描述、文章内容），它们可能会占用大量磁盘空间，并且还会增加文档的 blob 组件所使用的内存。对于之前未能完全适应 RAM 的索引，作为字符串属性添加长文本意味着 **更少** 的可变长度属性（字符串、JSON、MVA）可以缓存到 RAM 中，从而导致性能不佳。由于大小增加，可能无法在内存中锁定 blob 组件（access\_blob\_attrs=mlock）。字符串属性应仅用于短文本，预计将执行非全文过滤、分组和排序操作，而不仅仅是检索。

另一方面，存储字段是一个单独的组件。文本仅从磁盘读取，如果有可用的 RAM，可以将 [docstore\_cache\_size](https://docs.manticoresearch.com/latest/html/conf_options_reference/searchd_program_configuration_options.html#docstore-cache-size) 设置为较高的值（GB）以在 RAM 中缓存存储字段。此外，存储字段默认是压缩的，占用的存储空间比字符串属性少。还有一些情况需要将文本存储在索引中，并且它们仅在输出时使用，根本不用于过滤/排序/分组。从资源管理的角度来看，将它们放在 blob 中并不是最佳选择。这类字符串的例子可以是产品代码或 UUID（它们应该是唯一的，对它们进行排序没有太大意义）。将它们移动到存储字段将使 blob 更小，意味着使用更少的 RAM，启动时加载更快，并且根据情况，允许 mlocking。这里可能出现的一个“问题”是，新字段可能在不搜索特定字段的全文匹配中发挥作用，因此使用 [ignore field search operator](https://docs.manticoresearch.com/latest/html/searching/extended_query_syntax.html) 排除它们被搜索可能是个好主意。
