1、索引
通俗地来讲,正向索引是通过key找value,反向索引则是通过value找key。
1.1. 正向索引(forward index)
- 以文档的ID为关键字(数据库的主键,唯一+非空),表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档
- 这种组织方法在建立索引的时候结构比较简单,建立比较方便且易于维护
- 优缺点: 检索效率太低,只能在一起简单的场景下使用
1.2. 反向索引(inverted index)
- 一般也被别人称之为倒排索引 。
- 倒排表以字或词为关键字进行索引,表中关键字所对应的记录表项记录了出现这个字或词的所有文档
- 一个表项就是一个字段,它记录该文档的ID和字符在该文档中出现的位置情况
- 优缺点
- 查询的时候由于可以一次得到查询关键字所对应的所有文档,所以查询效率高于正排索引
- 由于每个字或词对应的文档数量在动态变化,所以倒排表的建立和维护都较为复杂
1.3. 倒排索引的组成
倒排索引主要由**单词词典(Term Dictionary)和倒排列表(Posting List)**组成。
-
单词词典(Term Dictionary):
- 倒排索引的重要组成,记录所有文档的单词,一般都比较大,记录单词到倒排列表的关联信 息。
- 单词词典一般用 B+Trees (有序)来实现,存储在内存:
-
-
倒排列表(PostingList):
- 倒排列表记载了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息及频率(作关联性算分),每条记录称为一个倒排项(Posting)。
- 倒排列表存储在磁盘文件中,主要包含以下信息
- 文档 ID
- 单词频率(TF:Term Frequency)
- 位置(Position)
- 偏移(Offset)
1.4. 索引的更新策略
-
搜索引擎需要处理的文档集合往往都是动态集合,即在建好初始的索引后,不断有新文档进入系统,同时原先的文档集合内有些文档可能被删除或更改 -
动态索引通过在内存中维护临时索引,可以实现对动态文档和实时搜索的支持 -
当最初分配的内存将被使用完时,要考虑将临时索引的内容更新到磁盘索引中,以释放内存空间来容纳后续的新进文档。 -
-
索引基本更新思想
倒排索引 就是对初始文档集合建立的索引结构,一般单词词典都存储在内存,对应的倒排列表存储在磁盘文件中临时索引 是在内存中实时建立的倒排索引,其结构和前述的倒排索引是一样的,区别在于词 典和倒排列表都在内存中存储。新文档 进入系统时,实时解析文件并将其加入到临时索引结构中。删除文档 列表则用来存储已被删除的文档的相应的文档ID,形成一个文档ID列表。修改文档 可以认为是旧文档先被删除,然后系统在增加一篇新的文档,通过这种间接方式实现对内容更改的支持。 -
-
常用的索引更新策略主要有四种:完全重建策略、再合并策略、原地更新策略及混合策略。
1.4.1. 完全重建策略
- 完全重建策略是一个很直接的方法,当新增文档达到一定数量,将新增文档和原先的老文档进行合并,
- 然后利用建立静态索引的方式,对所有文档重新建立索引。新索引建立完成后,老的索引被遗弃释放 。
- 优缺点
- 因为重建索引需要较长时间,在进行索引重建的过程中,内存中仍然需要维护老索引来对用户的查询做出相应。
- 这种策略适合比较小的文档集合
1.4.2. 再合并策略
- 在合并过程中,需要依次遍历增量索引和老索引单词词典中包含的单词以及其对应的倒排列表,可以用两个指针分别指向增量索引和老索引目前需要合并的单词。
- 如果增量索引中指针指向的单词ID小于老索引中指针指向的单词ID,则说明这个单词在老索引中没有出现过,直接将这个单词对应的倒排列表写入新索引的倒排列表中,同时增量索引单 词指针指向下一个单词。
- 如果两个单词ID相等,则先将老索引中这个单词对应的倒排列表加入新索引,然后在把增量索引这个单词对应的倒排列表追加到其后。
- 如果新索引指向的单词ID大于老索引指针指向的单词ID,则直接将老索引中对应的倒排列表加入新索引的倒排文件中,老索引的单词指针指向下一个单词。 两个索引的所有单词都遍历完后,新索引建成。
- 再合并策略是效率非常高的一种索引策略,主要是因为在对老索引进行遍历时,因为已经按照 索引单词的词典顺序由低到高排好顺序,所以可以顺序读取文件内容,减少磁盘寻道时间。
- 对于老索引中的很多单词来说,尽管其倒排列表并为发生任何变化,但是也需要将其从老索引中读取出来并写入新索引中,这样就会造成很大的磁盘输入输出消耗。
1.4.3. 原地更新策略
- 在索引更新过程中,如果老索引的倒排列表没有变化,可以不需要读取这些信息,而只是对那些倒排列表变化的单词进行处理,或者是直接将发生变化的倒排列表追加到老索引的末尾,即只更新增量索引里出现的单词相关信息,这样就可以减少大量的磁盘读写操作,提升系统执行效率。
- 原地更新策略在初始建立的索引中,会在每一个单词的倒排列表末尾预留出一定的磁盘空间。当预留空间不足时,需要在 磁盘中找到一块完整的连续存储区,将增量索引对应的倒排列表追加到其后,实现倒排列表的 “迁移”工作。
- 原地更新策略出发点很好,但是实验数据证明其索引更新效率比再合并策略低。
- 对倒排列表的“迁移”是比较常见的。这个策略需要对磁盘可用空间进行维护和 管理,这种维护和查找成本非常高,这成为该方法效率的一个瓶颈。
- 存在数据迁移,某些单词及其对应的倒排列表会从老索引中溢出,这样就破坏了单词的连续性,导致在进行索引合并的时候不能进行顺序读取,必需维护一个单词到其倒排文件相应位置的映射表,这样不仅降低了磁盘读写速度,而且需要大量的内存来存储这种映射信息。
1.4.4. 混合策略
- 混合策略一般会将单词根据不同性质进行分类 ,不同类别单词,对其索引采取不同的索引更新策略。
- 常见的做法时:
- 根据单词的倒排列表长度进行区分
- 因为有些单词经常在不同的文档中出现,所以其对应的倒排列表较长,
- 而有些单词很少见,则其倒排列表就较短。
- 根据这一性质将单词划分为长倒排列表单词和短倒排列表单词。
- 长倒排列表单词采取原地更新策略,而短倒排列表单词则采取再合并策略
2、分词器
2.1. 定义
- 文本分析是把全文本转换一系列单词(term/token)的过程,也叫分词。Analysis是通过Analyzer来实现的。
- 分词器的作用就是把整篇文档,按一定的语义切分成一个一个的词条,目标是提升文档的召回率, 并降低无效数据的噪音。
- recall召回率,也叫可搜索性,指搜索的时候,增加能够搜索到的结果的数量。
- 降噪:指降低文档中一些低相关性词条对整体搜索排序结果的干扰。
2.2. 组成
- 分析器(analyzer)都由三种构件块组成的:character filters , tokenizers , token filters
- character filters 字符过滤器: 在一段文本进行分词之前,先进行预处理 比如说最常见的就是,过滤html标签(hello --> hello),& --> and(I&you --> I and you)
- tokenizers 分词器: 英文分词可以根据空格将单词分开,中文分词比较复杂,可以采用机器学习算法来分词。
- token filters Token过滤器: 将切分的单词进行加工。 大小写转换(例将“Quick”转为小写),去掉词(例如停用词像“a”、“and”、“the”等 等),或者增加词(例如同义词像“jump”和“leap”)
- analyzer = CharFilters(0个或多个) + Tokenizer(恰好一个) + TokenFilters(0个或多个)
2.3. 内置分词器
- Standard Analyzer - 默认分词器,按词切分,小写处理
- standard 是默认的分析器。它提供了基于语法的标记化(基于Unicode文本分割算法),适用于大多数语言
- Simple Analyzer - 按照非字母切分(符号被过滤), 小写处理
- simple 分析器当它遇到只要不是字母的字符,就将文本解析成term,而且所有的term都是小写的。
- Whitespace Analyzer - 按照空格切分,不转小写
- Whitespace 按照空格进行分词,不区分大小写,汉语不分词
2.4. 中文分词器
|