eaglet

本博专注于基于微软技术的搜索相关技术
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

HubbleDotNet 开源全文搜索数据库项目--内存索引

Posted on 2011-08-10 06:09  eaglet  阅读(7719)  评论(45编辑  收藏  举报

经过2周多的努力,HubbleDotNet 的内存索引功能终于搞好了。有了内存索引,搜索不再去读硬盘,实时性大大提高了。hubble的内存索引不同于lucene 的内存索引,本文将具体介绍一下hubble 的内存索引功能。

hubbledotnet 的内存索引被设计为一个可管理的可以持久化的内存索引,它和lucene 的内存索引有很大不同。lucene 的内存索引是不能持久化的,就是如果你用lucene 的内存索引,那么一旦机器重启,索引就没有了,要持久化,要同时做内存索引和文件索引。(lucene老版本是这样的,不知道新版本是否改进了)。另外 lucene 的内存索引是不可管理的,不能动态分配内存,所有索引全部加载到内存,如果索引很大,内存消耗非常大。hubbledotnet 的内存索引在设计上考虑到这些问题,下面具体谈谈。

索引的持久化

hubbledotnet 的内存索引采用了读写分离的设计。写索引还是写入到文件中,读索引从内存中读取。这样即使机器重启,索引也不会丢失。而且由于读写分离,查询时完全不读取硬盘,查询的响应时间基本上非常确定,实时性比读取文件要提高很多。对于一些实时性要求比较高的搜索项目,由于数据修改非常频繁,并且要实时显示,在这种情况下,不可能每次增量或修改都优化索引,这样必然导致产生大量的索引碎片,如果不采用内存索引,每次搜索时就要读取大量的文件,搜索速度会受到很大影响,采用内存索引后,不管有多少文件,都是从内存读取,这个问题就得到彻底的解决。

 

内存索引类型

image

 

如上图所示,要让表具备内存索引功能,只要在 tableinfo 中设置 RamIndexType 就可以了。

内存索引有如下4种类型:

NoCache : 这种类型表示不把索引加载到内存

Full: 这种类型表示把索引全部加载到内存

Dynamic: 这种类型表示动态加载内存,这个类型要和 RamIndex Min Load Size 参数配合使用,当一次读取超过最小加载大小时,将把相应的一块内存加载到内存中,这个最小加载大小的设置是为了控制加载内存的数量,较少的文件读取对搜索速度不会产生太大的影响,如果不论读取多少都加载到内存,会导致内存增长过快。最小加载大小默认值为80KB。hubbledotnet 的倒排索引压缩率比较高,每个文档在倒排索引中只占用2-4个字节,80KB大概相当于单个单词匹配2万到4万条记录左右。由于GC的大对象堆的门槛是85KB,所以我将这个默认值设置为80KB,以避免频繁到大对象堆中分配内存。

Small: 这种类型只对大小小于8MB的索引文件加载内存,这个类型主要用于那些索引更新比较频繁,且内存又不是很充裕的项目,因为这些项目往往会产生很多小的索引文件碎片。

内存管理

内存索引有个很重要的问题就是随着索引文件的增大和搜索覆盖索引的增大,内存会逐渐增长,我们必须要有一个机制来控制这个内存的总数,不能把内存全部用光。hubbledotnet 专门做了这方面的设计。

image

 

如上图所示,HubbleDotNet 提供了三个参数

RamIndexMemoryLimited: 这个参数指定内存索引的最大占用内存数,默认为64GB。一旦内存索引占用的内存数量超过这个设置或者hubbledotnet 发现申请内存时系统的物理内存可用数量少于100MB,这时HubbleDotNet 会对内存进行整理,将不经常访问的内存清除出去以腾出足够的内存。

RamIndexAllocedMemory: 这个参数是一个只读参数,它返回当前内存索引占用的内存数量。

LastSystemAvaliableMemory:这个参数是一个只读参数,它返回上一次分配内存时系统的可用物理内存数量。

 

设置最大内存数

设置最大内存数的方法很简单,只要执行如下语句就可以,比如我们要设置内存索引最大占用内存数为2GB,我们只要执行:

sp_configure 'RamIndexMemoryLimited', 2048

image

注意:这个参数的设置不需要重启Hubble服务,执行这个语句后,参数会立即生效。如果当前占用的内存数大于设置的内存数量,系统会自动整理内存,释放出多余的内存。

适用版本

1.1.5.4 版本及其以上版本

 

返回 HubbleDotNet 技术详解