为什么需要段合并
性能上 - 提高查询效率
-
新增的文档(addDocument)会缓存在内存索引结构中,在主动调用commit或者定时自动commit时,会将所有内存的缓存数据flush到磁盘生成新segment段文件(每个segment是一个独立的倒排索引),这样可能会导致短时间内的段数量暴增,每一个段文件都会消耗文件句柄、内存和cpu运行周期等资源。
-
更重要的是,每个搜索请求都必须轮流检查每个段文件然后汇总查询结果,所以段越多,搜索也就越慢。段数目越少,段文件遍历和查询结果汇总的开销越小;而且因为索引数目少,存储索引元数据的信息也少,使磁盘占用率得到提高。
-
假如每次addDocument后都调用commit,那么生成的新segment仅包含一个文档,这样新增N个文档会导致新生成N个segment段文件,如果是每k次addDocument后才调用commit,那么新增n个文档会导致新生成n/k个segment段文件,可见进行适量的文档缓存是必要的。
-
但是段文件数目越小,尺寸越大就越高效吗?也不一定,段文件本质上是一个索引,索引尺寸太大不仅可能使性能退化,而且还有内存占用大、加载时间长、更新代价高等等问题,所以结论是:1.Segment段文件应当保持在适当大小(具体大小值可能和内存大小、索引类型、磁盘性能等有关); 2.尽可能减小段文件数目。这样就需要我们不断进行段文件的合并,使的每个段文件大小较为均衡,以尽可能减少数目。
功能上 - 支持文档删除
-
机械硬盘的随机读写性能差,顺序读写性能高,所以索引文件的操作都尽可能使用顺序读写,这样无论是在索引加载还是在索引写入时,都能保证高性能。
-
段文件是基于磁盘的索引文件,因为磁盘的随机定位性能差,所以索引文件的更新、删除和修改都比较低效,因此段文件一经生成就不再修改,所有的文档变更都是通过生成新段文件来实现。
-
段合并的时候会将那些旧的已删除文档 从文件系统中清除。 被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中,一旦合并结束,新的段被flush到了磁盘,老的段被删除。
注意:合并大的段需要消耗大量的I/O和CPU资源,可能会影响搜索性能,因此通常需要限制合并的频率。
段文件不可变的优缺点
段文件生成后是不可修改的,这个性质的优点有:
-
不需要锁。
不存在写操作就不需要担心多进程同时修改数据的问题。 -
Linux文件系统会将读取过的文件缓存到内存中,由于文件不变,只要文件系统缓存中还有足够的空间,那么大部分读请求会直接请求内存,而不会命中磁盘。这提供了很大的性能提升。(这块有点疑问,支持修改就不能充分利用系统缓冲?)
-
段文件可以在写入磁盘前进行充分压缩,能够有效减少磁盘I/O和需要被缓存到内存的索引的数据量。
缺点有:
- 文档修改(更新)和删除必须通过重建索引来实现,这对文档更新/删除的实时性造成了很大的限制。
- 其他
网友评论