在这篇文章中,我们讨论了在 3.0.2 中引入的新数据加载选项。
包含数据的索引由几个组件组成,如字典、文档和命中列表、属性。整个索引并不是完全加载到 RAM 中,因为可能无法容纳,而是以不同的方式读取和加载其组件。
属性
属性默认加载到 RAM 中,但可以选择是否加载所有属性、仅加载标量类型(整数或浮点数)或将其保留在磁盘上。
属性以内存映射文件加载。使用 mmap()
加载属性的优点是比经典的寻道和读取使用 pread()
更高的性能。它还允许使用小量的 RAM 来处理大文件。
在 2.x 中,属性加载是通过 ondisk_attrs
处理的。即使我们选择将属性加载到 RAM 中,使用 mmap()
读取整个文件也不能保证文件的页面会保留在 RAM 中,因为操作系统内核可以释放它们(这对应用程序不是问题,因为映射文件由磁盘上的文件本身支持)。为了确保属性保持在 RAM 中并且操作系统不会将其换出到磁盘中,需要使用 mlock
。
在 3.0.2 中,我们决定进行更改,而不是为了加载哪个属性类型而有一个设置和一个用于 mlocking 的设置,而是有两个设置,每个属性类型分别决定它们如何加载以及是否应被锁定。
新设置是
access_blob_attrs
- 管理可变长度属性(字符串,JSON,MVA) -
和 access_plain_attrs
- 管理固定长度属性(uint,bigint,float,timestamp,bool)。可选值有 mmap
、mmap_preread
和 mlock
。
从旧指令切换到新指令相对简单:
ondisk_attrs = 0
意味着没有属性留在磁盘上,它们预先读取到 RAM 中。这是与 mlock=0 的默认值。这现在相当于access_blob_attrs = mmap_preread
和access_plain_attrs= mmap_preread
。当所有属性都可以容纳在 RAM 中时应使用此模式。为了确保它们不被换出到磁盘,我们可以改为使用access_blog_attrs = mlock
和access_plain_attrs = mlock
,相当于ondisk_attrs=0
和mlock=1
。ondisk_attrs=1
意味着所有属性都留在磁盘上。使用新的选项,您必须指定access_blob_attrs=mmap
和access_plain_attrs=mmap
。ondisk_attrs=pool
意味着让字符串、JSON 和 MVA 属性留在磁盘上。要得到相同的效果,现在需要执行access_blob_attrs=mmap
和access_plain_attrs=mmap_preread
。
但现在也可以将数字属性保留在磁盘上,而加载可变长度属性(通过执行 access_blob_attrs=mmap_preread
/access_plain_attrs=mmap
),例如如果您没有足够的 RAM 来容纳所有属性,并且您的查询在可变长度属性上执行更多操作(过滤、分组、排序)。
还可以仅对某些属性进行 mlocking。例如,我们希望数字属性确保它们留在 RAM 中,但其他属性可以在 RAM 中预先读取,但我们接受不锁定它们,以腾出一些可以释放的内存空间。
全文索引
全文索引的部分本身包括多个组件。字典组件(.spi)总是被加载到 RAM 中,因为它对全文搜索性能至关重要,并且它的大小不大。文档列表(.spd)保存索引词与文档和字段的引用。这个组件通常很大,直到通过使用 pread() 访问。
全文索引的另一个组件是命中列表(.spp
),它包含字段中单词的位置。命中列表也可以很大(但不如文档列表大),并以与文档列表相同的方式访问。从 3.0.2 开始,这两个组件可以使用 mmap()
而不是 pread()
加载,使用
access_doclists
和 access_hitlists
。该设置接受两个值:file
(使用 pread()
并且是默认的)和 mmap
。
如何设置内存指令?
默认情况下,全文索引组件使用文件,而所有属性使用 mmap_preread,这是内存使用和搜索性能之间最平衡的配置。
为了确保加载到内存中的属性数据不被操作系统丢弃,可以使用 mlock。锁定应该在有足够内存容纳属性的系统上进行,但也要为文档/命中列表留出足够的内存。当索引可以完全加载/缓存到 RAM 中时,最佳性能将会实现。使用文件方法的文档/命中列表可以通过将其文件发送到 /dev/null 来预热。
对于希望从第一个查询获得最佳性能的情况,可以使用 searchd 的 --force-preread
选项。这个选项应谨慎使用,因为守护进程在启动完成之前不会响应传入查询。对于单一设置,这意味着不可能进行搜索查询,这在完成启动所需的时间与在此期间进行响应之间可能不可接受。
如果索引大于可用内存或可以接受较长的预热时间,则应使用简单的 file
/mmap
。如果索引无法很好地适应 RAM,则性能将受到存储性能的影响。在更多内存和更快存储之间的选择取决于每个的成本。更快的存储(如 NVMe)将减少内存不足的缺陷。拥有足够的内存但存储速度较慢意味着启动或索引重新加载会更慢,性能将在索引加载到内存中之前受到影响。