1、 倒排拉链如果很长如何处理
(1)倒排拉链的长度是有限制的,这个长度限制是亿级别的,所以一般不会超出,如果真的超出就会截断
(2)可能超出长度的是一些停用词,如果超出就会截断,并且停用词在建立倒排的时候,位置信息只建立一个,因为这些词一般无意义只是为了召回,如果位置信息太多,在后续计算proximity score的时候比较耗时,这些需要处理的词是挖掘好的词表
2、如何提升索引检索的性能
(1)索引分区
索引可以分区,按照termid分区即可,这样取一个term的doclist的时候,首先将term转化为termid,然后termid%分区数就可以hash到这个termid的索引块,然后在这个索引块中进行二分查找找到这个termid对应的doclist
(2)索引查找
索引查找主要使用的是跳表查找,先看一下数据结构
首先word的doclist在物理机上存储的基本单位是section,每个section中存储一定量的doclist,假设某个word的doclist有1024个,每个section可以存储512个docid,那么这个word需要两个section,如果有多个section,那么多个section可以使用跳表连接起来
在section内部,doclist也是有大小顺序的,这样这些doclist也可以再次使用跳表结构
其中section级别的跳表有1级,doclist级别的跳表有2级
struct qsrchSEGItem {
uint32_t _M_offset;
uint32_t _M_size;
// 当前segment最小docid
uint32_t _M_skipdoc;
};
struct qsrchDOCHead {
uint64_t _M_basedoc:32;
// 当前section最小docid
uint64_t _M_skipdoc:32;
…
}
1、首先倒排列表被分配到多个sectiont中,每个section默认8192个倒排id,如果倒排id有10000个那么这个倒排列表被分配到2个sectiont中
2、sectiont之间是和sectiont内部的doc是逆序排列的,也就是有序的,这样就可以形成跳表结构了
3、查询sectiont,每次查询先查询sectiont的最大id以及sectiont的size,如果目标在id-size之间,就定位了sectiont
4、在sectiont内部查找目标,原理同查找section差不多
(3)查找顺序
查找的时候先把倒排拉链按照长短排序,先找用短的查找长的;而且在查找的时候一个doc查完才查另一个doc,例如
word1 : 1 3 5 6
word2 : 1 3 5 8 10 12
word3: 1 2 5 7 10 14 16 18
先把word按照查找倒排长短排序,短的在前,然后word1中先用1查找word2中的1,找到以后再查找word3中的1,如果都查找到则这个docid 1为有效docid。
然后word1中用3查找word2中的3,找到以后再找word3中的3,发现没有找到那么docid3 不是有效id
(4)索引压缩
索引压缩的基本单位是section,索引压缩的主要用途是为了减少磁盘io操作,否则磁盘占用的块会比较多,比较消耗io