Lucene解析 - 基本概念

摘要: 前言 Apache Lucene是一个开源的高性能、可扩展的信息检索引擎,提供了强大的数据检索能力。Lucene已经发展了很多年,其功能越来越强大,架构也越来越精细。它目前不仅仅能支持全文索引,也能够提供多种其他类型的索引方式,来满足不同类型的查询需求。

前言

Apache Lucene是一个开源的高性能、可扩展的信息检索引擎,提供了强大的数据检索能力。Lucene已经发展了很多年,其功能越来越强大,架构也越来越精细。它目前不仅仅能支持全文索引,也能够提供多种其他类型的索引方式,来满足不同类型的查询需求。
基于Lucene的开源项目有很多,最知名的要属Elasticsearch和Solr,如果说Elasticsearch和Solr是一辆设计精美、性能卓越的跑车,那Lucene就是为其提供强大动力的引擎。为了驾驭这辆跑车让它跑的更快更稳定,我们需要对它的引擎研究透彻。
在此之前我们在专栏已经发表了多篇文章来剖析Elasticsearch的数据模型、读写路径、分布式架构以及Data/Meta一致性等问题,这篇文章之后我们会陆续发表一系列的关于Lucene的原理和源码解读,来全面解析Lucene的数据模型和数据读写路径。
Lucene官方对自己的优势总结为几点:
  1. Scalable, High-Performance Indexing
  2. Powerful, Accurate and Efficient Search Algorithms
希望通过我们的系列文章,能够让读者理解Lucene是如何达到这些目标的。
整个分析会基于Lucene 7.2.1版本,在读这篇文章之前,需要有一定的知识基础,例如了解基本的搜索和索引原理,知道什么是倒排、分词、相关性等基本概念,了解Lucene的基本使用,例如Directory、IndexWriter、IndexSearcher等。


基本概念

在深入解读Lucene之前,先了解下Lucene的几个基本概念,以及这几个概念背后隐藏的一些东西。

如图是一个Index内的基本组成,Segment内数据只是一个抽象表示,不代表其内部真实数据结构。
Index(索引)
类似数据库的表的概念,但是与传统表的概念会有很大的不同。传统关系型数据库或者NoSQL数据库的表,在创建时至少要定义表的Scheme,定义表的主键或列等,会有一些明确定义的约束。而Lucene的Index,则完全没有约束。Lucene的Index可以理解为一个文档收纳箱,你可以往内部塞入新的文档,或者从里面拿出文档,但如果你要修改里面的某个文档,则必须先拿出来修改后再塞回去。这个收纳箱可以塞入各种类型的文档,文档里的内容可以任意定义,Lucene都能对其进行索引。
Document(文档)
类似数据库内的行或者文档数据库内的文档的概念,一个Index内会包含多个Document。写入Index的Document会被分配一个唯一的ID,即Sequence Number(更多被叫做DocId),关于Sequence Number后面会再细说。
Field(字段)
一个Document会由一个或多个Field组成,Field是Lucene中数据索引的最小定义单位。Lucene提供多种不同类型的Field,例如StringField、TextField、LongFiled或NumericDocValuesField等,Lucene根据Field的类型(FieldType)来判断该数据要采用哪种类型的索引方式(Invert Index、Store Field、DocValues或N-dimensional等),关于Field和FieldType后面会再细说。
Term和Term Dictionary
Lucene中索引和搜索的最小单位,一个Field会由一个或多个Term组成,Term是由Field经过Analyzer(分词)产生。Term Dictionary即Term词典,是根据条件查找Term的基本索引。
Segment
一个Index会由一个或多个sub-index构成,sub-index被称为Segment。Lucene的Segment设计思想,与LSM类似但又有些不同,继承了LSM中数据写入的优点,但是在查询上只能提供近实时而非实时查询。
Lucene中的数据写入会先写内存的一个Buffer(类似LSM的MemTable,但是不可读),当Buffer内数据到一定量后会被flush成一个Segment,每个Segment有自己独立的索引,可独立被查询,但数据永远不能被更改。这种模式避免了随机写,数据写入都是Batch和Append,能达到很高的吞吐量。Segment中写入的文档不可被修改,但可被删除,删除的方式也不是在文件内部原地更改,而是会由另外一个文件保存需要被删除的文档的DocID,保证数据文件不可被修改。Index的查询需要对多个Segment进行查询并对结果进行合并,还需要处理被删除的文档,为了对查询进行优化,Lucene会有策略对多个Segment进行合并,这点与LSM对SSTable的Merge类似。
Segment在被flush或commit之前,数据保存在内存中,是不可被搜索的,这也就是为什么Lucene被称为提供近实时而非实时查询的原因。读了它的代码后,发现它并不是不能实现数据写入即可查,只是实现起来比较复杂。原因是Lucene中数据搜索依赖构建的索引(例如倒排依赖Term Dictionary),Lucene中对数据索引的构建会在Segment flush时,而非实时构建,目的是为了构建最高效索引。当然它可引入另外一套索引机制,在数据实时写入时即构建,但这套索引实现会与当前Segment内索引不同,需要引入额外的写入时索引以及另外一套查询机制,有一定复杂度。
Sequence Number
Sequence Number(后面统一叫DocId)是Lucene中一个很重要的概念,数据库内通过主键来唯一标识一行,而Lucene的Index通过DocId来唯一标识一个Doc。不过有几点要特别注意:
  1. DocId实际上并不在Index内唯一,而是Segment内唯一,Lucene这么做主要是为了做写入和压缩优化。那既然在Segment内才唯一,又是怎么做到在Index级别来唯一标识一个Doc呢?方案很简单,Segment之间是有顺序的,举个简单的例子,一个Index内有两个Segment,每个Segment内分别有100个Doc,在Segment内DocId都是0-100,转换到Index级的DocId,需要将第二个Segment的DocId范围转换为100-200。
  2. DocId在Segment内唯一,取值从0开始递增。但不代表DocId取值一定是连续的,如果有Doc被删除,那可能会存在空洞。
  3. 一个文档对应的DocId可能会发生变化,主要是发生在Segment合并时。
Lucene内最核心的倒排索引,本质上就是Term到所有包含该Term的文档的DocId列表的映射。所以Lucene内部在搜索的时候会是一个两阶段的查询,第一阶段是通过给定的Term的条件找到所有Doc的DocId列表,第二阶段是根据DocId查找Doc。Lucene提供基于Term的搜索功能,也提供基于DocId的查询功能。
DocId采用一个从0开始底层的Int32值,是一个比较大的优化,同时体现在数据压缩和查询效率上。例如数据压缩上的Delta策略、ZigZag编码,以及倒排列表上采用的SkipList等,这些优化后续会详述。


索引类型

Lucene中支持丰富的字段类型,每种字段类型确定了支持的数据类型以及索引方式,目前支持的字段类型包括LongPoint、TextField、StringField、NumericDocValuesField等。
如图是Lucene中对于不同类型Field定义的一个基本关系,所有字段类都会继承自Field这个类,Field包含3个重要属性:name(String)、fieldsData(BytesRef)和type(FieldType)。name即字段的名称,fieldsData即字段值,所有类型的字段的值最终都会转换为二进制字节流来表示。type是字段类型,确定了该字段被索引的方式。

FieldType是一个很重要的类,包含多个重要属性,这些属性的值决定了该字段被索引的方式。

Lucene提供的多种不同类型的Field,本质区别就两个:一是不同类型值到fieldData定义了不同的转换方式;二是定义了FieldType内不同属性不同取值的组合。这种模式下,你也能够通过自定义数据以及组合FieldType内索引参数来达到定制类型的目的。

要理解Lucene能够提供哪些索引方式,只需要理解FieldType内每个属性的具体含义,我们来一个一个看:

  • stored: 代表是否需要保存该字段,如果为false,则lucene不会保存这个字段的值,而搜索结果中返回的文档只会包含保存了的字段。

  • tokenized: 代表是否做分词,在lucene中只有TextField这一个字段需要做分词。

  • termVector: 这篇文章很好的解释了term vector的概念,简单来说,term vector保存了一个文档内所有的term的相关信息,包括Term值、出现次数(frequencies)以及位置(positions)等,是一个per-document inverted index,提供了根据docid来查找该文档内所有term信息的能力。对于长度较小的字段不建议开启term verctor,因为只需要重新做一遍分词即可拿到term信息,而针对长度较长或者分词代价较大的字段,则建议开启term vector。Term vector的用途主要有两个,一是关键词高亮,二是做文档间的相似度匹配(more-like-this)。

  • omitNorms: Norms是normalization的缩写,lucene允许每个文档的每个字段都存储一个normalization factor,是和搜索时的相关性计算有关的一个系数。Norms的存储只占一个字节,但是每个文档的每个字段都会独立存储一份,且Norms数据会全部加载到内存。所以若开启了Norms,会消耗额外的存储空间和内存。但若关闭了Norms,则无法做index-time boosting(elasticsearch官方建议使用query-time boosting来替代)以及length normalization

  • indexOptions: Lucene提供倒排索引的5种可选参数(NONE、DOCS、DOCS_AND_FREQS、DOCS_AND_FREQS_AND_POSITIONS、DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS),用于选择该字段是否需要被索引,以及索引哪些内容。

  • docValuesType: DocValue是Lucene 4.0引入的一个正向索引(docid到field的一个列存),大大优化了sorting、faceting或aggregation的效率。DocValues是一个强schema的存储结构,开启DocValues的字段必须拥有严格一致的类型,目前Lucene只提供NUMERIC、BINARY、SORTED、SORTED_NUMERIC和SORTED_SET五种类型。

  • dimension:Lucene支持多维数据的索引,采取特殊的索引来优化对多维数据的查询,这类数据最典型的应用场景是地理位置索引,一般经纬度数据会采取这个索引方式。
来看下Lucene中对StringField的一个定义:
 
StringFiled有两种类型索引定义,TYPE_NOT_STORED和TYPE_STORED,唯一的区别是这个Field是否需要Store。从其他的几个属性也可以解读出,StringFiled选择omitNorms,需要进行倒排索引并且不需要被分词。


Elasticsearch数据类型

Elasticsearch内对用户输入文档内Field的索引,也是按照Lucene能提供的几种模式来提供。除了用户能自定义的Field,Elasticsearch还有自己预留的系统字段,用作一些特殊的目的。这些字段映射到Lucene本质上也是一个Field,与用户自定义的Field无任何区别,只不过Elasticsearch根据这些系统字段不同的使用目的,定制有不同的索引方式。
举个例子,上图​是Elasticsearch内两个系统字段_version和_uid的FieldType定义,我们来解读下它们的索引方式。Elasticsearch通过_uid字段唯一标识一个文档,通过_version字段来记录该文档当前的版本。从这两个字段的FieldType定义上可以看到,_uid字段会做倒排索引,不需要分词,需要被Store。而_version字段则不需要被倒排索引,也不需要被Store,但是需要被正排索引。很好理解,因为_uid需要被搜索,而_version不需要。但_version需要通过docId来查询,而且Elasticsearch内versionMap内需要通过docId做大量查询且只需要查询出_version字段,所以_version最合适的是被正排索引。
关于Elasticsearch内系统字段全面的解析,可以看下这篇文章


总结

这篇文章主要介绍了Lucene的一些基本概念以及提供的索引类型。后续我们会有一系列文章来解析Lucene提供的IndexWriter的写入流程,其In-Memory Buffer的结构以及持久化后的索引文件结构,来了解Lucene为何能达到如此高效的数据索引性能。也会去解析IndexSearcher的查询流程,以及一些特殊的查询优化的数据结构,来了解为何Lucene能提供如此高效的搜索和查询。


原文链接

干货好文,请关注扫描以下二维码:



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/522001.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FileZilla 下载安装使用

我电脑是win10 64位的,不知软件为何这样命名,已经用了2年多了。 FileZilla 版本:3.27.1下载链接 http://gainetsoftwares.kuaiyunds.com/gainetsoftwares/FileZilla3d0899f3-d291-4714-bd45-027ffaa49962.zip 1、 双击FileZilla_3.27.1_win3…

Vicor再携创新产品“登陆”ODCC大会,有详情!

戳蓝字“CSDN云计算”关注我们哦!目前,越来越多的应用系统对电源系统的功率密度及转换效率提出了更高要求,在电源系统设计中不仅功率密度是众多要素之一,其他例如电源系统架构、多种开关拓扑、电源模块和基于分立器件设计的封装技…

Lucene 查询原理

摘要: # 前言 Lucene 是一个基于 Java 的全文信息检索工具包,目前主流的搜索系统Elasticsearch和solr都是基于lucene的索引和搜索能力进行。想要理解搜索系统的实现原理,就需要深入lucene这一层,看看lucene是如何存储需要检索的数…

mac解压rar命令_苹果mac电脑上很好用的免费压缩软件?ezip压缩软件分享

在开始之前,先问问用苹果电脑的大家一个问题,有没有遇到过这种情况呢?就是好不容易在网上找到了需要的素材,然后下载回来后发现,想解压却解压不了。因为mac系统自带的压缩工具是不支持rar格式的,而在网上很…

如何从机器学习数据中获取更多收益

摘要: 本文讲解一些关于机器学习数据集的小技巧,分享个人经验,可供读者参考。对于深度学习而言,合适的数据集以及合适的模型结构显得至关重要。选择错误的数据集或者错误的模型结构可能导致得到一个性能不佳的网络模型&#xff0c…

CSDN×易观算法大赛火热进行中~

伴随着5G、物联网与大数据形成的后互联网格局的逐步形成,日益多样化的用户触点、庞杂的行为数据和沉重的业务体量也给我们的数据资产管理带来了不容忽视的挑战。为了建立更加精准的数据挖掘形式和更加智能的机器学习算法,对不断生成的用户行为事件和各类…

该放弃正在堕落的“RNN和LSTM”了

摘要: 随着技术的发展,作者觉得是时候放弃LSTM和RNN了!到底为什么呢?来看看吧~递归神经网络(RNN),长期短期记忆(LSTM)及其所有变体:现在是放弃它们…

textarea支持a标签_微慕小程序开源版A标签优化说明

微慕WordPress小程序所有版本里,对于文章详情里文字内容的解析,都是通过开源组件:wxParse;不过这个组件已经停止维护,微慕小程序在这个组件上做了一些优化,让文章里文字在小程序显示更加完美。但&#xff0…

七本书籍带你打下机器学习和数据科学的数学基础

摘要: 本文主要介绍七本关于机器学习和数据科学数学基础的经典教材,是一份不可多得的书单整理。大多数人学习数据科学的重心放在编程上面,然而,要真正精通数据科学的话是不能够忽视数据科学背后的数据基础。本篇文章,将…

奇葩面试官让我回去等通知!看我怎么虐他!

戳蓝字“CSDN云计算”关注我们哦!作者 | 农翻身刘鑫来源 | 码农翻身后记:已经发了两篇漫画了,一个是《我才是世界上最好的语言》,还有一个是《HTTP之大明邮差》,前两篇主要讲技术,这一篇是娱乐性质&#xf…

阿里:千亿交易背后的0故障发布

摘要: 阿里巴巴千亿交易背后,如何尽量避免发布故障?在面对实际运维过程中遇到的问题该如何解决?近日,在刚刚结束的 GOPS深圳站大会上,阿里巴巴运维技术专家少荃,给我们带来了解决方案和思路。前…

华为麒麟990芯片发布;谷歌宣布开源创新隐私保护技术;阿里20亿美元全资收购网易考拉;中国联通将设立100亿5G创新基金……...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 东风新款电动车菱智M5 EV上市…

C++继承和组合——带你读懂接口和mixin,实现多功能自由组合

摘要: 本文详细介绍了C继承的三种方式和相关重要概念,整理了众多继承与组合中的注意问题。在C继承存在不安全的默认实现,非虚函数的覆盖,多重继承的函数名冲突、菱形继承等众多问题下,如何实现多个功能的自由组合&…

如何在阿里云•对象存储OSS托管用户域名的https证书

摘要: OSS服务支持将用户域名绑定到OSS域名,并为此用户域名提供HTTPS证书托管服务。以满足用户使用自己的域名也能支持HTTPS安全加密的访问方式传输数据。面向人群您已经拥有了自己的域名。您已将或准备将自己的域名绑定到OSS域名上,并且使用…

win10系统VMware Workstation与Device/Credential Guard不兼容怎么办

解决方法: 打开本电脑-》管理-》服务和应用程序-》服务下找到如下图的HV 主机服务,双击选择禁用。 或者 转到“ 控制面板” >“ 卸载程序” >“ 打开或关闭Windows功能”以关闭Hyper-V。 步骤二:通过命令关闭Hyper-V(控制…

数据大爆炸边缘期 让存储告别旧时代

戳蓝字“CSDN云计算”关注我们哦!好莱坞一部高智商大数据电影《永无止境》,讲述一位落魄的作家库珀,服用了一种可以迅速提升智力的神奇蓝色药物。他将这种高智商用于炒股,能在短时间掌握无数公司资料和背景,也就是将世…

AliOS Things图形界面开发指南

简介物联网设备开发过程中,嵌入式GUI(用户图形界面)的开发是一个重要的组成部分。许多智能设备如智能家电、智能手表、智能仪表上都会涉及到GUI开发。AliOS Things集成开源图形库littlevGL,可以在linux上进行图形界面开发。开发完…

微服务的好处与弊端_《微服务架构设计模式》-学习总结07

本篇主要总结第七章:在微服务架构中实现查询在微服务架构中查询数据的挑战何时以及如何使用API组合模式实现查询 何时以及如何使用CQRS模式实现查询 微服务架构中,查询通常需要检索分散在多个服务所拥有的数据库中的数据,跨服务数据查询的两种…

ECS主动运维2.0,体验升级,事半功倍

摘要: 阿里云致力于提供更好用的运维体验,让您使用ECS的过程更透明、高效,并实现更加标准化、自动化的运维方式。基于主动运维2.0,您使用ECS云服务器的体验更加流畅,而且利用系统事件,不再依赖于工单联系客…

mysql bench如何下载_MySQLWorkbench下载与使用教程详解

一、MySQL Workbench的下载Workbench是MySql图形化的管理工具,可以在Workbench里输入MySql的语句,这可能更适合大多数人的视觉,有些操作更能更简单化首先我们下载workbench然后选择download选择no thanks,just download下载后点击…