用es也差不多一年左右了,但是都是只会用,底层做了什么一窍不通,没有核心竞争力,循序渐进,一个一个攻破,理解的多了,读的多了,自然能力就上去了,es底层是基于lucene的,所以今天先从lucene下手

如何看lucene代码? 现在的代码太多,可能会比较干扰阅读,我找了最初代的lucene代码,只有750k,先看下

lucene1.4文档翻译整理:

/*
每个索引里有以下这几类文件:
field names: 存储该段中所有的属性名
stored field values: 每个文档每个field的原始值,跟db的格式差不多
term dictionary: 包含这个段中所有索引属性的词元,包含词元的文本、包含该词元的文档数,还有指向该词元频率数据(在文档中出现的次数)和位置数据(这个词元在文档中的位置,相对于哪里?位置的格式是什么样的?)的指针
term frequency data: 词元频率数据,所有在词元字典中出现的词元被哪些文档包含,以及每个文档中出现该词元的次数
term proximity data: 词元位置数据,所有在词元字典中出现的词元在所属文档中的位置
normalization factors: 每个文档的每个属性都会存储一个命中因子分,当该属性被搜索结果命中的时候会将该值乘上命中的得分作为最终的得分
term vectors: 词元向量,每个文档的每个属性都存储一个词元列表,每个词元项包含词元的单词以及词元的频率(什么数据?) 在词元字典中已经存储了词元的所有信息,为什么还要在这里按照文档和属性纬度来存储词元信息 文件名格式:
每个段下面的文件都有相同的文件名,但是有不同的后缀以区分不同的功能,一个索引下的所有段不必须在一个文件夹下 lucene1.4的数据类型
lucene索引数据是以字节为单位,有以下几种数据类型:
byte: 字节型,所有其他的数据类型都是基于字节做的封装
Uint32: 32位无符号整型值,4个字节,高字节优先(就是从后往前看,为什么要高字节优先?)
Uint64: 64位无符号整形值,8字节,高字节优先
Vint: 变长整形值,该类型可能包含多个字节,仍然是高字节优先,每个字节的第一位不存储数据值,存储后面是否还有字节的标示
chars: 存储字符按照UTF-8编码的unicode编码
String: string是复合数据类型,首先是一个Vint标示字符串有多长,然后跟chars 索引级别文件:
segments: 记录该索引下所有段的信息,
格式为: Format,Version,SegCount,<SegName,SegSize> * SegCount。
Format用于标示lucene版本
Version记录索引被修改了多少次,比如增加、删除文档
SegCount表示段的个数
剩下的是按顺序放置的段信息,每个段包含段名和该段包含的文档个数
commit.lock: 当该文件存在的时候,表示有进程正在重写segments文件和删除过期的段索引文件,或者进程正在读取segments文件和segments文件中记录的段索引文件。这个文件锁的作用就是在当前进程读取或者写segments文件后,正准备读或者写segments文件中记录的段索引文件时禁止其他进程删除段索引文件。
write.lock: 当该文件存在时,表示正有进程在添加文档到索引或者正在删除索引文件,该文件锁防止在一个进程在操作时其他进程修改索引数据 段级别文件:
.fnm([f]ield [n]a[m]e): 记录该段中所有的属性信息,
格式为:FieldsCount,<FieldName,FieldBits> * FieldsCount
FieldsCount表示属性个数(如果该段中不同的文档属性个数不一样怎么办? 这里存的是超集?)
FieldName: 属性名
FieldBits: 记录该属性的一些配置信息,第一位字节表示该属性是否索引,第二位表示该属性是否有词元向量数据
在其他文件中的属性编号也是在该文件中记录的,属性在这个文件中的顺序就是它的编号,第一个是0,第二个是1.。。。。
.fdt([f]ield [d]a[t]a): 该文件中记录了该段中所有文档的原始数据,类似于数据库格式: 每一行一个文档,每一列为一个属性
格式为: <DocFieldData> * SegSize
DocFieldData就是每个文档的数据
DocFieldData格式为: FieldCount,<FieldNum,Bits,Value> * FieldCount
FieldCount表示该文档的属性
Bits的第一位表示该属性是否分词(为什么是否分词是对每个文档设置的?不是应该对所有文档设置的么?)
Value就是属性值
.fdx([f]ield [d]ata inde[x]): 该文件是为了方便通过文档号查询该文档的属性数据(就是上面的fdt里的数据),
格式为:<FieldValuesPosition> * SegSize
FieldValuesPosition表示的是某个文档的属性数据在上面fdt文件中的偏移,类型为Uint64,8字节,比如要找编号为0的文档的属性数据,那就到该文件(.fdt)文件中的 0 * 8字节处读取出来一个值,然后去上面的属性值文件中去用这个值表示偏移处取出来值就是该文档的属性数据。 已上都是属性相关的文件,下面开始词元相关的文件 首先是词元字典:
词元字典文件包含两个文件,一个是词元信息文件,一个是词元信息索引文件
.tis([t]erm [i]nfo[s]): 存储词元信息
格式为: TIVersion,TermCount,IndexInterval,SkipInterval,<TermInfo> * TermCount
TermCount表示有多少个词元
IndexInterval是用于词元信息索引文件中用的,词元信息索引文件就是把该文件中按照IndexInterval间隔取出来一些词元放到词元信息索引文件中,方便对词元信息文件的随机访问
TermInfo的格式为: Term,DocFreq,FreqDelta,ProxDelta,SkipDelta
Term就表示的词元,词元的存储是按照前缀公用的形式,就是前后两个词元如果前缀有相同的,那后一个词元只用存后缀就行了,格式为: <PrefixLength,Suffix,FieldNum>, PrefixLength表示和前一个词元重合的前缀长度,Suffix表示词元的后缀,FieldNum表示该词元所属的属性的编号
DocFreq表示有多少文档包含该词元
FreqDelta表示词元频率数据在.frq文件中的偏移,存储的形式是前一个该数据的差值,比如第一个词元的该值为100,第二个词元的该值为150,那第二个词元存储的该值就是150 - 100 = 50
ProxDelta表示词元在文档中出现的位置的数据在.prx文件中的偏移,存储形式跟FreqDelta一样
SkipDelta表示该词元SkipData数据(不知道这个数据是干什么用的)在.frq文件中的偏移,因为.frq文件中已经存储了词元的频率数据,而每个词元都有频率数据和SkipData数据,成对出现,在.frq文件中的每个词元先存储频率数据,再存储SkipData数据,所以这个SkipDelta存储的是这个SkipData所属的词元的频率数据的字节长度,这样通过频率数据的偏移 + 频率数据的长度 就是这个词元的SkipData数据
.tii([t]erm [i]nfo [i]ndex): 存储词元信息索引数据,这里存储的是上面.tis文件中IndexInterval指定的间隔的词元信息
格式为: IndexTermCount,<TermInfo,IndexDelta> * IndexTermCount
IndexTermCount表示该文件中一共有多少个索引词元
TermInfo和上面.tis文件中一样
IndexDelta表示当前这个词元在.tis文件中的偏移,存储的形式也是差值存储,就是后面词元存储的该值是前一个词元该值的差 然后是词元频率文件,上面词元字典里存的每个词元都包含一个FreqDelta就是指向该文件中指定词元位置的
.frq([f][r]e[q]uency): 存储词元频率数据
格式为:<TermFreqs,SkipData> * TermCount
TermFreqs存储了词元的的频率数据,包括哪些文档包含了该文档,该词元在每个文档中的出现的频率
TermFreqs是一个列表,里面每个项是包含该词元的某个文档以及该词元在该文档中出现的次数,SkipData就是按照上面词元字典里存储的SkipInterval间隔,将TermFreqs里指定项的相关属性存储起来,所以SkipData也是一个列表,这个列表的长度等于TermFreqs的长度除以IndexInterval
TermFreqs的格式为 <TermFreq> * DocFreq
DocFreq和上面词元字典里存的是一样的
TermFreq的格式为: DocDelta,Freq?
DocDelta和Freq都是Vint类型的值,lucene为了节省存储空间,用DocDelta的最后一位来决定是否需要存储Freq的值,如果Freq=1,则不单独用Vint存储Freq了,将DocDelta的值向左移动一位,然后最后空出来的一位设置为1,如果Freq>1,则也需要将DocDelta左移一位,空出来的最后一个设置为0,Freq用单独的一个Vint存储
SkipData的格式:<SkipDatum> * (DocFreq / SkipInterval)
SkipData就是从TermFreqs列表中按照SkipInterval抽取出来的子集,然后在设置一些额外的属性,所以SkipData是一个列表
SkipDatum格式为: <DocDelta,FreqDelta,ProxDelta>
DocDelta表示按照SkipInterval抽取出来的文档ID,比如现在TermFreqs里存储了35个文档数据,SkipInterval的值为16,那SkipData列表里存储的DocDelta列表为 15,31
FreqDelta存储了TermFreqs里指定项(词元 + 包含该词元的某文档)相对于.frq文档开始的字节数,为了节省存储空间按照差值规则存储
ProxDelta存储了TermFreqs里指定项(词元 + 包含该词元的某文档)相对于.prx文件文档开始出的字节数,为了节省存储空间按照差值规则存储 下面是位置数据
.prx(position,不知道这个文件名是怎么取的): 这个文件里存的是每个词元在某个文档中出现的位置
格式为:<TermPositions> * TermCount
这个TermCount和词元字典里存储的TermCount是一样的
TermPositions格式为: <Postions> * DocFreq
DocFreq和词元字典里的DocFreq是一样的,存储了有多少个文档包含了该词元
Postions存储了每个文档中该词元的位置,格式为: <PositoinDelta> * Freq
Freq表示这个词元在这个文档中出现的次数,在frq文件中的DocFreq里存储的有这个值
PositoinDelta是Vint类型的值,存储了这个词元在这个文档中出现的具体位置,(好像没有说这个里存储的是字节数还是词元数)为了节省存储空间,该值也是使用差值存储规则 最后一个关于词元的文件是一系列词元向量文件,这几个文件建立了文档到词元的关联关系
.tvf(term vector for field): 这个是存储了属性到词元的关联文件
格式为: TVFVersion<NumTerms,NumDistinct,TermFreqs> * NumFields
NumFields是属性的个数,这个我理解应该是该段中的所有属性个数,和fnm文件中存储的FieldsCount一样
NumTerms是该属性包含的所有词元数
NumDistinct没有用
TermFreqs存储了词元的文本值和词元的频率数据指针,指向.frq文件中该词元的数据
TermFreqs格式为: <TermText,TermFreq> * NumTerms
TermText就是词元的文本,使用前缀规则存储节省空间
TermFreq是一个Vint类型的数据,记录了.frq文件中该词元的数据位置
.tvd(term vector for document): 这个文件存储了文档到属性的关联关系,这里的属性指的是上面.tvf里的属性
格式为: TVDVersion,<NumFields,FieldNums,FieldPositions> * NumDocs
NumDocs表示该段中的文档数,和索引级别文件segments中存储的segSize应该是一样的
NumFields标识该文档中的属性数
FieldNums格式为<FieldDelta>*NumFields,存储的是所有属性的编号,这里的编号对应于.fnm文件里体现的编号
FieldPositions存储了这些属性到.tvf文件中的指针,格式为: <FieldPosition> * NumFields
tvx(term vector index): 这个文件是tvd文件的索引文件,方便通过文档编号随机访问tvd用的
格式为: TVXVersion<DocumentPosition> * NumDocs
DocumentPosition是一个固定Uint64类型的数字,直接通过文档编号 * 8在这个文件中存储的值就是tvd文件中的偏移量 在官方文档里少了个.cfs文件,1.4版本的lucene在最后会将所有的文件和合并到一个文件里,不知道为什么要这么做,cfs文件格式为:
  .cfs格式为: 文件数量,<文件内容偏移,文件名> * 文件数量,<文件内容> * 文件数量
  
*/

elasticsearch原理学习的更多相关文章

  1. elasticsearch原理学习笔记

    https://mp.weixin.qq.com/s/dn1n2FGwG9BNQuJUMVmo7w 感谢,透彻的讲解 整理笔记 请说出 唐诗中 包含 前  的诗句 ...... 其实你都会,只是想不起 ...

  2. Elasticsearch原理学习--为什么Elasticsearch/Lucene检索可以比MySQL快?

    转载于:http://vlambda.com/wz_wvS2uI5VRn.html 同样都可以对数据构建索引并通过索引查询数据,为什么Lucene或基于Lucene的Elasticsearch会比关系 ...

  3. ElasticSearch 5学习(10)——结构化查询(包括新特性)

    之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...

  4. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

  5. ElasticSearch 5学习(7)——分布式集群学习分享2

    前面主要学习了ElasticSearch分布式集群的存储过程中集群.节点和分片的知识(ElasticSearch 5学习(6)--分布式集群学习分享1),下面主要分享应对故障的一些实践. 应对故障 前 ...

  6. ElasticSearch 5学习(6)——分布式集群学习分享1

    在使用中我们把文档存入ElasticSearch,但是如果能够了解ElasticSearch内部是如何存储的,将会对我们学习ElasticSearch有很清晰的认识.本文中的所使用的ElasticSe ...

  7. ElasticSearch 5学习(5)——第一个例子(很实用)

    想要知道ElasticSearch是如何使用的,最快的方式就是通过一个简单的例子,第一个例子将会包括基本概念如索引.搜索.和聚合等,需求是关于公司管理员工的一些业务. 员工文档索引 业务首先需要存储员 ...

  8. ElasticSearch 5学习(2)——Kibana+X-Pack介绍使用(全)

    Kibana是一个为 ElasticSearch 提供的数据分析的 Web 接口.可使用它对日志进行高效的搜索.可视化.分析等各种操作.Kibana目前最新的版本5.0.2,回顾一下Kibana 3和 ...

  9. IIS原理学习

    IIS 原理学习 首先声明以下内容是我在网上搜索后整理的,在此只是进行记录,以备往后查阅只用. IIS 5.x介绍 IIS 5.x一个显著的特征就是Web Server和真正的ASP.NET Appl ...

随机推荐

  1. SQLServer常用快捷键汇总

    菜单激活键盘快捷键 操作 SQL Server 2017 SQL Server 2008 R2 移到 SQL Server Management Studio 菜单栏 Alt Alt 激活工具组件的菜 ...

  2. Skyshop.Detail Maps

    Secondary Maps(Detail Maps) & Detail Mask 增加模型细节,而不需要使用单张的超大贴图. 应用:增加皮肤细节,比如毛孔:砖墙添加细小的裂缝和青苔:大型金属 ...

  3. APP自动化环境配置

    做自动化很多人都不喜欢做app自动化,说实话,我也不喜欢做app自动化,但是没办法,老板给你钱,让你做,不得不做! 其实app自动化的难点就在于环境,环境OK了之后一切都和web自动化差不多,顶多就是 ...

  4. 第18.2节_地址类型与LL层设备过滤

    一.地址类型 二.白名单和Resolving List 三.LL层设备过滤 一.地址类型 学习资料:官方手册 Vol 6: Core System Package [Low Energy Contro ...

  5. github配置密钥

    我们在githob创建项目后,本地使用git 克隆代码 需要在githob配置密钥,才可以 步骤: 下载git,进行安装,安装好后.点击桌面,右键,选择>>git  bash 在弹出的黑框 ...

  6. python27期day17:re、logging日志模块、作业。

    1.re: 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 re 模 ...

  7. wal2json docker 试用

    基于官方的release 构建了一个docker 镜像,以下是测试使用 环境准备 docker-compose 文件 version: "3" services:   mypg: ...

  8. ESA2GJK1DH1K升级篇: 快速的移植升级程序到自己的项目(APP用户程序制作)

    前言 用户程序比较简单,但是起着至关重要的作用 用户程序是和BootLoader程序相互配合的 拷贝文件到自己的项目 APP用户程序的 stmflash.c stmflash.h 和 上一节的Boot ...

  9. tornado之获取参数

    self.write()  # 返回字符串 self.redirect()  # 重定向 self.render()  # 返回html页面 一. 获取url中携带的参数, 如: 127.0.0.1: ...

  10. 复杂模拟 | 1014 模拟K个同时到来的人在N个窗口,每个窗口只能站M个人的银行排队

    这题我以为还是之前银行排队的思路,但是做着做着就做不下去了了.看了答案我才理解到底是什么个思路. 是这样的:不同于之前排队的题,这里的K个人是同时到来的.所以首先应该让K个人的前N*M(也就是黄线内的 ...