基于luncene倒排索引实现大规模数据集检索优化(一)基础知识篇

原理探索(基础知识)

检索

在一组记录集合中找到关键码值等于给定值的某个记录,或者找到关键码值符合特定条件的某些记录的过程 (key,value)

  • 检索效率非常重要

  • 尤其对于大数据量

  • 需要对数据精选特殊的存储处理

提高检索效率的方法
1)预排序
  • 排序算法本身比较费时

  • 只是预处理(在检索之前已经完成)

2)建立索引
  • 检索式重复利用辅助索引信息,以空间换时间

  • 牺牲一定的空间

  • 从而提高检索效率

3)散列技术
  • 把数据组织到一个表中

  • 更具关键码的值确定表中记录的位置

  • 缺点1: 不适合进行范围查询

  • 缺点2:一般也不允许出现重复关键码

基本数据

1)输入顺序文件

按照记录进入系统的顺序存储记录

输入顺序文件相当于一个磁盘中未排序的线性表,不支持高效率的检索

2)主码,主键

数据库中每条记录的唯一标识,但是只有主码,不便于各种灵活检索

3)辅码

可以出现重复值的码

辅码索引把一个辅码值与具有这个辅码值的每一条记录的主码值关联起来

大多数检索利用辅码索引来完成

4)索引

把关键码和它对应的数据记录的位置相关联的过程

  • (关键码,指针)对,(key,pointer)

  • 指针指向主要数据库文件即主文件中的完整记录

索引文件

记录这种联系的文件组织结构

  • 一个主文件可以有多个相关索引文件

-每个索引文件往往支持一个关键码字段

-不需要重新排列重排主文件

  • 可以通过该索引文件高效访问记录中该关键码值

索引技术

- 高效率的检索

- 插入、更新、删除

稠密索引 Vs 稀疏索引
  1. 稠密索引:每一个记录建立一个索引项

  1. ----主文件不按照关键码顺序排列

  1. 稀疏索引:对一组记录建立一个索引项

  1. 记录按照关键码的顺序存放

  1. 可以把记录分成多个组(块)

  1. 索引指针指向的这一组记录在磁盘中的起始位置

线性索引
  • 按照关键码的顺序进行排序

  • 文件中的指针指向存储在磁盘上的文件记录起始位置或主索引中主码的起始位置

1)线性索引问题

线性索引太大,存在磁盘中

  • 在一次检索过程中可能多次访问磁盘,从而影响检索效率

  • 使用二级线性索引

更新线性索引

  • 在数据库中插入或删除记录时

  1. 二级线性索引

静态索引

  • 索引结构在文件创建、初始装入记录时生成

  • 一旦生成就固定下来,在系统运行(例如插入和删除记录过程中索引结构并不改变)

  • 只有当文件再组织才允许改变索引结构

多分树
  • 组织索引一般不用二叉树而采用多分树

  • 大大减少访问外存的次数

isam

基于多分树的ISAM

  • 为磁盘存取而设计

  • 结构采用多级索引

  • 主索引

  • 柱面索引

  • 磁道索引

  • 现在已经被B+树的VSAM取代

倒排索引

意义解读

当我们需要查找文本数据中的某些内容时,最简单的方法就是遍历整个文本,检查其中是否包含需要查找的内容。现代信息检索系统需要处理海量数据,手工检索难以适应需要。全文数据库,也成为文本数据库,是管理大量文本的系统。有别于传统的结构化数据,文本为典型的非结构化数据,所以全文数据库的实现手段以及全文索引的结构模型完全不同于传统数据库。全文检索的关键技术便是索引的建立以及维护,索引文章中每一个词,对每一个词进行索引,当用户查询时,检索程序更具事先简历好的索引进行查找。并将查找结果反馈给用户的检索方式。 此时,倒排索引就可以发挥作用。

倒排索引是一种数据结构,它通过将单词映射到出现该单词的文档列表,来加速查找文本数据中的内容。倒排索引可以分为两个部分:词典和倒排表。

词典是由文本中所有不同的单词组成的列表,每个单词有一个唯一的标识符。在建立索引时,需要将文本中的每个单词与词典中的单词进行匹配,并分配唯一的标识符。

倒排表则是一个记录每个单词在哪些文档中出现过的列表。对于每个单词,倒排表中都会记录它出现的文档列表,以及在每个文档中出现的位置。这个列表可以是一个数组、链表或哈希表等数据结构。

通过使用倒排索引,当用户需要查找一个单词时,搜索引擎可以直接在倒排表中查找该单词,并返回包含该单词的文档列表。这个过程非常高效,因为只需要在文档集合中检查包含该单词的文档,而不是遍历整个文本集合。

倒排索引,以关键词所谓索引关键字和链表访问入口的索引结构,用来存储全文检索下某个关键词在文档或一组文档中的存储位置的映射。

传统倒排索引模型。扫描每个文本对每个文本产生一组三元组(文本号,词频,字符文中位置)。然后对所有三元组以字符内码(拼音)排序。

倒排索引建立方式

当我们需要对一些文本数据建立倒排索引时,可以采用以下步骤:

  1. 分词:将文本数据切分成若干个单词,通常使用分词器(Tokenizer)来实现。

  1. 建立倒排表:对于每个单词,将它出现的文档和位置记录在倒排表中。

  1. 建立词典:将所有不同的单词记录在词典中,并分配唯一的标识符。

举例

我给出一个中文文本数据的例子,来展示如何建立倒排索引:

假设我们有以下三个中文文档:

文档1:中国有句俗话叫做“物以类聚,人以群分”。

文档2:众所周知,中国是一个多民族国家。

文档3:中国的首都是北京。

首先,需要对中文文本进行分词,可以使用中文分词器将文本切分成单词,得到以下单词列表:

中国,有,句,俗话,叫做,物以类聚,人以群分,众所周知,是,一个,多,民族,国家,的,首都,是,北京

接下来,需要建立倒排表。对于每个单词,记录它出现的文档和位置。例如,对于单词 "中国",它在文档 1、文档 2 和文档 3 中出现过。在文档 1 中出现的位置是 1,文档 2 中出现的位置是 2,文档 3 中出现的位置是 1。因此,倒排表中 "中国" 的记录如下:

中国: 文档1(1), 文档2(2), 文档3(1)
对于其他单词,也可以按照相同的方式建立倒排表。最终,我们得到了以下倒排表:
中国: 文档1(1), 文档2(2), 文档3(1)
有: 文档1(2)
句: 文档1(3)
俗话: 文档1(4)
叫做: 文档1(5)
物以类聚: 文档1(6)
人以群分: 文档1(7)
众所周知: 文档2(1)
是: 文档2(3), 文档3(2)
一个: 文档2(4)
多: 文档2(5)
民族: 文档2(6)
国家: 文档2(7)
的: 文档3(1), 文档3(3)
首都: 文档3(2)
北京: 文档3(3)

最后,需要建立词典,将所有不同的单词记录在词典中,并分配唯一的标识符。例如,可以使用以下方式建立词典:

中国: 1
有: 2
句: 3
俗话: 4
叫做: 5
物以类聚: 6
人以群分: 7
众所周知: 8
是: 9
一个: 10
多: 11
民族: 12
国家: 13
的: 14
首都: 15
北京: 16

通过这种方式建立倒排索引

两种倒排方式

基于属性的倒排和对正文的倒排虽然都是使用倒排索引技术,但它们所针对的数据内容不同,应用场景也有所区别。基于属性的倒排更适合处理具有结构化属性信息的数据集,例如商品、新闻等,而对正文的倒排则更适合处理文本数据集,例如电子书、论文等。

基于属性的倒排

对于基于属性的倒排,它针对的是文档的属性信息,例如作者、时间、文档类型等。在基于属性的倒排中,每个属性值都会对应一个包含该属性值的文档列表。当用户查询某个属性值时,系统会通过倒排索引找到该属性值对应的文档列表,从而快速地返回与该属性值相关的所有文档。

概念
  • 对某属性按照属性值建立索引表,称倒排表

  • (属性--指针)对 即(arr,ptrList)

  • 属性值,具有该属性值的各记录指针

  • 指针可以是关键码,或该记录的主文件地址

  • 颠覆主文件顺序,因而称为倒排索引

  • 属性往往是离散的

  • 对于连续性的索引,往往用B树

  • 倒排文件:带有倒排索引的文件

优点
  • 能够对于基于属性的检索进行较高效率的处理

缺点
  • 花费了保存倒排表的存储代价

  • 降低了更新运算的效率

对正文的倒排

而对于对正文的倒排,它则是针对文档内容的倒排。在对正文的倒排中,每个单词都会对应一个包含该单词的文档列表。当用户查询某个关键词时,系统会通过倒排索引找到包含该关键词的所有文档列表,从而快速地返回与该关键词相关的所有文档。

概念

建立一个数据结构以提供对文本内容的快速检索

  • 词索引(word index)

  • 全文索引(full-text index)

两种索引方式

词索引(term index)和全文索引(full-text index)是常见的两种索引方式,它们的区别在于索引的粒度和范围不同。

词索引
基本思想:
  • 把正文看成由符号和词所组成的集合,从正文中抽取关键词,然后用这些关键词组成一些适合快速检索的数据结构。

  • 适用于多种文本类型,特别是那些可以很容易就解析成一组词的集合的文本

  • 适用于英文

  • 中文等需要经过切词

词索引使用最广泛

一个已经排过序的关键词的列表

  • 其中每个关键词指向一个倒排

  • 指向该关键词出现文档的集合

  • 在文档中的位置

全文索引
基本思想:
  • 把正文看作一个长的字符串

  • 在数据结构中记录的是子字符串的开始位置

  • 查询就可以针对正文中的任何子字符串

可以对每一个字符建立索引,从而使查询词不再受限与关键词

需要跟大的空间

举例子

假设我们有一个包含三个中文文档的数据集,文档内容如下:

文档1:北京的天气真好,适合出去玩。

文档2:上海的天气有点热,最好待在家里。

文档3:广州的天气多云,适合旅游。

针对这个数据集,我们可以分别建立词索引和全文索引。

如果是建立词索引,那么对于每个中文词语,我们都会记录下包含该词语的文档列表。例如,对于词语 "北京",我们会记录下包含该词语的文档列表为文档1;对于词语 "适合",我们会记录下包含该词语的文档列表为文档1和文档3。这样,当用户查询某个关键词时,系统会通过词索引找到包含该关键词的文档列表,从而快速地返回与该关键词相关的所有文档。

如果是建立全文索引,那么对于每个文档,我们会记录下文档中出现的所有中文词语。例如,对于文档1,我们会记录下所有中文词语 "北京"、"的"、"天气"、"真好"、"适合"、"出去"、"玩";对于文档2,我们会记录下所有中文词语 "上海"、"的"、"天气"、"有点"、"热"、"最好"、"待在"、"家里"。这样,当用户查询某个关键词时,系统会在全文索引中查找包含该关键词的文档。

可以看出,建立词索引和全文索引的区别在于索引的粒度和范围。在中文文本中,单个词语可能包含多个字,因此词索引一般会先对中文文本进行分词处理,然后针对每个分出来的词语进行索引。而全文索引则是将整个文本作为一个完整的对象来建立索引,不需要进行分词处理。

下面是一个法律文书的例子:

法律文书:
原告王某诉被告李某损害人身权纠纷一案,本院认为...
倒排索引(InvertedIndex):
{
    "原告": [1],
    "王某": [1],
    "诉": [1],
    "被告": [1],
    "李某": [1],
    "损害": [1],
    "人身权": [1],
    "纠纷": [1],
    "本院": [1],
    "认为": [1]
}
​
词索引(TermIndex):
{
    "原告": [1],
    "王某": [1],
    "诉": [1],
    "被告": [1],
    "李某": [1],
    "损害": [1],
    "人身权": [1],
    "纠纷": [1],
    "本院": [1],
    "认为": [1],
    "原告王某诉被告李某损害人身权纠纷一案本院认为": [1]
}
全文索引(Full-TextIndex):
{
    "原告王某诉被告李某损害人身权纠纷一案,本院认为...": [1]
}

在这个例子中,倒排索引、词索引和全文索引分别记录了该法律文书中出现的关键词和文本。例如,词索引记录了文书中每个单词出现的位置,全文索引则记录了整个文书的内容。当用户查询关键词时,搜索引擎会根据索引方式返回不同的查询结果。例如,如果用户查询关键词 "原告",词索引和倒排索引会返回包含该词的文档列表,而全文索引则会返回整个法律文书。

倒排索引结构

当使用倒排索引构建搜索引擎时,需要一个数据结构来存储所有的索引项。常用的倒排索引结构包括以下两个部分:

  1. 索引表(Posting List):对于每个单词,需要存储包含该单词的文档信息列表。这个列表包括所有包含该单词的文档 ID 或文档地址。索引表也可以记录每个单词在文档中的位置信息,这样就可以进行短语搜索等高级查询。

  1. 倒排索引(Inverted Index):由多个索引表构成的数据结构。倒排索引的每个索引表都记录了一个单词和包含该单词的文档列表。倒排索引通过单词来查找包含该单词的文档列表,因此称为倒排索引。对于一个查询单词,搜索引擎会查找倒排索引,找到包含该单词的所有文档,然后通过一定的算法排序返回。

假设有如下三篇法律文书:

法律文书1:
原告王某诉被告李某损害人身权纠纷一案,本院认为...
​
法律文书2:
本案原告李某与被告王某存在劳动争议,本院认为...
​
法律文书3:
原告王某与被告张某签订了一份房屋租赁合同,本院认为...
基于这三篇法律文书,构建的倒排索引可以如下所示:
索引表(PostingList):
{
    "原告": [
        {"doc_id": 1, "pos": [1]},
        {"doc_id": 2, "pos": [2]},
        {"doc_id": 3, "pos": [1]}
    ],
    "被告": [
        {"doc_id": 1, "pos": [2]},
        {"doc_id": 2, "pos": [1]},
        {"doc_id": 3, "pos": [2]}
    ],
    "人身权": [
        {"doc_id": 1, "pos": [4]}
    ],
    "劳动争议": [
        {"doc_id": 2, "pos": [4]}
    ],
    "房屋租赁合同": [
        {"doc_id": 3, "pos": [4, 5, 6]}
    ]
}
​
倒排索引(InvertedIndex):
{
    "原告": [1, 2, 3],
    "被告": [1, 2, 3],
    "人身权": [1],
    "劳动争议": [2],
    "房屋租赁合同": [3]
}

在这个例子中,索引表(Posting List)中包含了每个关键词在每篇文书中出现的位置信息。例如,"原告" 这个索引表记录了该关键词在文书1、文书2和文书3中的出现位置,其中在文书1中出现在第1个位置,文书2中出现在第2个位置,文书3中出现在第1个位置。

而倒排索引(Inverted Index)则是由多个索引表构成的数据结构,用于快速查找包含某个关键词的文书。例如,当用户输入关键词 "原告" 时,搜索引擎会查找倒排索引中的 "原告" 索引表,从而返回包含该关键词的文书列表 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不会只能哭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值