正排索引
概念
正排表是以文档的ID为key,表中记录文档中每个关键字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档。
特点
这种组织方法在建立索引的时候结构比较简单,建立比较方便且易于维护;
因为索引是基于文档建立的,若是有新的文档加入,直接为该文档建立一个新的索引块,挂接在原来索引文件的后面。
若是有文档删除,则直接找到该文档号文档对应的索引信息,将其直接删除。
但是在查询的时候需对所有的文档进行扫描以确保没有遗漏,这样就使得检索时间大大延长,检索效率低下。
倒排索引
概念
倒排表以字或词为关键字进行索引,表中关键字所对应的记录表项记录了出现这个字或词的所有文档,
一个表项就是一个字表段,它记录该文档的ID和字符在该文档中出现的位置情况。
特点
每个字或词对应的文档数量在动态变化,所以倒排表的建立和维护都较为复杂,
但是在查询的时候由于可以一次得到查询关键字所对应的所有文档,所以效率高于正排表。
在全文检索中,检索的快速响应是一个最为关键的性能,而索引建立由于在后台进行,尽管效率相对低一些,但不会影响整个搜索引擎的效率。
示例:
假设对象为商品,特征为关键词。下面举例说明一下什么是正排索引,什么是倒排索引。
对于每个商品,我们将它的标题和描述进行分词,然后可以建立如下正排索引
(key是商品id,value是该商品的各个关键词的出现次数和出现位置):
商品1 -> [(关键词1,出现3次,位置为1,3,5), (关键词2,出现2次,位置为2,6), (关键词4,出现1次,位置为10), …]
商品2 -> [(关键词1,出现1次,位置为1), (关键词3,出现4次,位置为2,4,7,9), …]
商品3 -> [(关键词2,出现2次,位置为1,4), (关键词4,出现3次,位置为2,7,10), …]
商品4 -> [(关键词5,出现1次,位置为1), (关键词6,出现1次,位置为2), …]
同时我们也可以建立如下倒排索引
(key是关键词,value是包含该关键词的商品id列表):
关键词1 -> [商品1,商品2]
关键词2 -> [商品1,商品3]
关键词3 -> [商品2]
关键词4 -> [商品1,商品3]
关键词5 -> [商品4]
关键词6 -> [商品4]
用户搜索商品这个场景中,搜索引擎会做这么几个事情:
①将用户输入的文字进行分词,比如说得到[关键词1,关键词4];
②对于关键词1,根据倒排索引,发现命中[商品1,商品2];
③对于关键词4,根据倒排索引,发现命中[商品1,商品3];
④那么符合条件的商品就包括[商品1,商品2,商品3],下面就需要使用正排索引来对它们进行排序,我们简单定义一下匹配度计算公式为目标关键词出现次数的总和(当然真实商业场景不可能只有匹配度这么一个维度这么简单粗暴。可能要关联数十上百个正排索引,比如匹配度、热度、好评率、给我们广告费非的多少等等很多指标综合决定);
⑤对于商品1,使用正排索引计算得到匹配度为3+1=4;
⑥对于商品2,使用正排索引计算得到匹配度为1;
⑦对于商品3,使用正排索引计算得到匹配度为3;
⑧根据匹配度从高到低,最终搜索的排序结果为:[商品1,商品3,商品2]
因此总的来说倒排索引用于召回,从茫茫海洋中把所有符合条件的对象搜索出来;正排索引用于排序,把最符合搜索结果、对用户(或者是商家 or 平台)价值最高的对象放到首位。
注:
其中词典结构尤为重要,有很多种词典结构,各有各的优缺点,最简单如排序数组,通过二分查找来检索数据,更快的有哈希表,磁盘查找有B树、B+树,但一个能支持TB级数据的倒排索引结构需要在时间和空间上有个平衡,下图列了一些常见词典的优缺点: