1 索引构建
索引构建
建立倒排索引的过程,就是索引构建
索引器
构建索引的程序或者计算机,就是索引器
索引器需要原始文本,但是文档可能采用多种编码格式,索引器对中间文件和最后的索引文件进行压缩或者解压缩,在web搜索中,文档往往并不是来自本地,必须要通过网络采集才能得到。
2 索引的硬件基础
一个2007年度的典型计算机系统的参数如下表所示
符号 | 含义 | 值 |
---|---|---|
s | 平均寻道时间 | 5 ms |
b | 每个字节的传输时间/处理器时钟频率 | 0.02 us/ 10^9 Hz |
p | 底层操作时间 | 0.01 us |
内存大小 | G为单位 | |
磁盘大小 | 1 TB 或者更大 |
注:寻道时间指的是将磁头移动到新位置所花的时间,每个字节的传输时间指的是磁头就位以后从磁盘到内存的传输速率
与IR系统设计相关的硬件参数:
-
访问内存数据比访问磁盘数据快得多,因此我们会更可能地设计数据放到内存中
-
为使数据传输速率最大,连续读取的数据块也应该联系存放在磁盘上
-
操作系统以数据块为单位进行读写,因此,从磁盘读取一个字节和读取一个数据块的时间可能差不多
-
磁盘I/O时处理器可以同时处理数据,因此,假设采用一种高效率的解压缩算法的话,读磁盘压缩数据再解压比直接读取未压缩数据的时间要更少
-
IR系统的服务器一半有G或者数G的内存,可用的磁盘空间一般比内存大小要高几个数量级
3 基于块的排序索引方法
由于内存不足,必须采用基于磁盘的外部排序算法。为了达到可以接受的速度,对该算法的核心思想要求是:在排序时尽量减少磁盘随机寻道的次数。
基于块的排序索引算法(BSBI, blocked sort-based indexing algorithm)
- 将文档集分割成几个大小相等的部分
- 将每个部分的词项ID-文档ID对排序
- 将中间产生的临时排序结果存放到磁盘中
- 将所有的中间文件合并成最终的索引
基于快的排序索引算法将每个块的倒排索引存储文件 f1 ,...fn 中,最后合并成文件fmerged。
基于块的排序索引算法.png具体过程可以细化为:
- 对词项ID-文档ID进行排序
- 将具有同一词项ID的所有文档ID放到倒排记录表中,其中每条倒排记录仅仅对应一个文档ID
- 将基于块的倒排索引写到磁盘上
- 将多个块索引合并到一个索引文件
基于块的倒排索引合并过程:将两个块从磁盘读入内存,然后在内存中进行合并,最后写回磁盘。
基于块的排序索引算法的合并过程.png时间复杂度:O(T logT),因为具有最高时间复杂度的步骤是排序,T是排序的项目数量上限(例如termID-docID对的数量)。但实际的索引时间通常由解析文档(ParseNextBlock)和完成最终合并(MergeBlocks)所花费的时间决定的。
优缺点:该算法有很好的扩展性,但是需要一种将词项映射成其ID的数据结构,对于大规模的文档集合来说,该数据结构会很大,在内存中难以存放。
4 内存式单遍扫描索引构建方式
SPIMI(single-pass in-memory indexing,内存式单遍扫描索引算法)。SPIMI 使用词项而不是其 ID,它将每个块的词典写入磁盘,对于下一个块则重新采用新的词典。只要硬盘空间足够大,SPIMI 就能够索引任何大小的文档集。
SPIMI 算法的流程如图所示,其中省略了文档分析以及将文档转换成词项—文档 ID 流(算 法中称为 token_stream)的过程。反复调用 SPIMI-INVERT 函数直到将全部的文档集处理完为止。
SPIMI算法中倒排索引的生成.png
BSBI 和 SPIMI 的区别
- 这个算法与上面的算法一上来就有直接不同的特点就是他无须做id的转换,还是采用了词对索引的直接关联。还有1个比较大的特点是他不经过排序,直接按照先后顺序构建索引,算法的主要步骤如下:
- 对每个块构造一个独立的倒排索引。
- 最后将所有独立的倒排索引进行合并就OK了。
5 分布式索引构建方法
在实际当中,文档集通常都很大,在单台计算机上很难高效地构建索引,因此Web搜索引擎通常使用分布式索引构建,索引结果也是分布式的,往往按照词项或者文档进行分片后分布在多台计算机上。
MapReduce 是一个通用的分布式计算架构,面向大规模计算机集群而设计,其主要思想是利用价格低廉的日用计算机来解决大型的计算问题。Map和Reduce阶段将计算任务划分成子任务块,以便每个工作节点在短时间内快速处理。
-
裂片:输入数据(网页集合)被分割成n个数据片
-
分配:运行过程中,主控节点将数据片分给计算的任务节点
-
Map阶段:将输入的数据片映射成键值对,也称为分析器阶段。每个分析器将输出结果存在本地的中间文件。
-
Reduce阶段:将同一健(词项ID)的所有值(文档ID)集中存储,以便快速读取和处理。
-
倒排器:给定一个健(词项ID),将所有的值(文档ID)汇总并组织成倒排表的过程由reduce阶段的倒排器来完成。
Map和Reduce的架构
map : 输入 -> list(k, v)
reduce : (k, list(v)) -> 输出
索引构建中上述架构的变化
map : web 文档集合
-> list(词项ID, 文档ID)
reduce : (<词项ID1,list(docID)>, <词项ID2,list(docID)>)
-> (倒排记录表1, 倒排记录表2)
分析器和倒排器不一定是不同的机器,主控节点发现空闲的机器后会分配新的任务。同一台机器在map阶段中可以作为分析器,在reduce阶段也可以作为倒排器。索引构建的同时,机器上往往可以运行其他任务,除了分析器和倒排器之外,也可以作为网络爬虫等其他任务。
6 动态索引构建
在实际中,大部分文档集合会随文档的增加、删除和修改而不断改变,这也意味着需要将新的词项加入词典,并对已有词项的倒排记录表进行更新。
索引更新方法:周期性地对文档集合从头开始进行索引重构。
实时性:要实时检索到新文档,可以采用辅助索引。辅助索引存储新文档信息,记录在内存中,检索时同时遍历两个索引。文档的删除记录保存在一个无效位向量中。
引入辅助索引的解决办法:
同时保持两个索引:一个是大的主索引,另一个是小的用于存储新文档信息的辅助索引(auxiliary index) ,后者保存在内存中。检索时可以同时遍历两个索引并将结果合并。每当辅助索引变得很大时,就将它合并到主索引中。文档的删除操作记录在一个无效位向量(invalidation bit vector)中,在返回结果之前可以利用它过滤掉已删除文档。某篇文档的更新通过先删除后重新插入来实现。
主辅索引合并分析:
- 主辅索引的构建索引办法会导致合并过于频繁(内存索引变大时就得进行合并操作),合并时如果正好在搜索,那么搜索的性能将很低
- 理想情况下,如果将每个词项的倒排记录表都单独存成一个文件,那么要合并主索引和辅助索引,只需要将辅助索引的倒排记录表扩展到主索引对应的倒排记录表即可完成。遗憾的是,由于绝大多数文件系统不能对大数目的文件进行高效处理,因此将每个倒排记录表存成一个文件这种方式实际是不可行的。另一种简单的方法是将索引存到一个大文件中,也就说将所有倒排记录表存到一起。
- 现实当中常常介于上述两者之间(例如:将大的倒排记录表分割成多个独立的文件,将多个小倒排记录表存放在一个文件当中)
对数合并
- 维护一系列的索引I0,I1,I2,…,每个都是前一个的两倍大小20n,21n,22*n,…。n是辅助索引Z0的大小。
- 辅助索引Z0存储在内存中。
- 将较大的那些(I0,I1,I2,…)存储在磁盘中。
- 当Z0达到上限n时,将它写入磁盘的I0中。
当Z0下一次达到上限时,它会和I0合并,生成Z1(大小21*n)
对数合并.png
网友评论