elasticsearch原理学习
用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原理学习的更多相关文章
- elasticsearch原理学习笔记
https://mp.weixin.qq.com/s/dn1n2FGwG9BNQuJUMVmo7w 感谢,透彻的讲解 整理笔记 请说出 唐诗中 包含 前 的诗句 ...... 其实你都会,只是想不起 ...
- Elasticsearch原理学习--为什么Elasticsearch/Lucene检索可以比MySQL快?
转载于:http://vlambda.com/wz_wvS2uI5VRn.html 同样都可以对数据构建索引并通过索引查询数据,为什么Lucene或基于Lucene的Elasticsearch会比关系 ...
- ElasticSearch 5学习(10)——结构化查询(包括新特性)
之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...
- ElasticSearch 5学习(9)——映射和分析(string类型废弃)
在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...
- ElasticSearch 5学习(7)——分布式集群学习分享2
前面主要学习了ElasticSearch分布式集群的存储过程中集群.节点和分片的知识(ElasticSearch 5学习(6)--分布式集群学习分享1),下面主要分享应对故障的一些实践. 应对故障 前 ...
- ElasticSearch 5学习(6)——分布式集群学习分享1
在使用中我们把文档存入ElasticSearch,但是如果能够了解ElasticSearch内部是如何存储的,将会对我们学习ElasticSearch有很清晰的认识.本文中的所使用的ElasticSe ...
- ElasticSearch 5学习(5)——第一个例子(很实用)
想要知道ElasticSearch是如何使用的,最快的方式就是通过一个简单的例子,第一个例子将会包括基本概念如索引.搜索.和聚合等,需求是关于公司管理员工的一些业务. 员工文档索引 业务首先需要存储员 ...
- ElasticSearch 5学习(2)——Kibana+X-Pack介绍使用(全)
Kibana是一个为 ElasticSearch 提供的数据分析的 Web 接口.可使用它对日志进行高效的搜索.可视化.分析等各种操作.Kibana目前最新的版本5.0.2,回顾一下Kibana 3和 ...
- IIS原理学习
IIS 原理学习 首先声明以下内容是我在网上搜索后整理的,在此只是进行记录,以备往后查阅只用. IIS 5.x介绍 IIS 5.x一个显著的特征就是Web Server和真正的ASP.NET Appl ...
随机推荐
- (八)OpenStack---M版---双节点搭建---Cinder安装和配置
↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 1.创建数据库并授权 2.获得admin凭证执行管理员命令并创建服务证书 3.创建块存储设备AP ...
- 流程及迭代驱动测试管理软件, itest 发布到开源中国
itest 源码已发布到码云 ,项目已被开源中国收录!详见 https://www.oschina.net/p/itest-cn 测试人自己开发,汇聚10年沉淀,独创流程驱动测试.度量展现测试人价值 ...
- Rust中的控制结构
fn main() { let number = ; { println!("condition was true"); } else { println!("condi ...
- mac下命令行安装node.js及切换不同版本nodejs
摘自: http://www.cnblogs.com/ikuyka/p/5825762.html 前提是你电脑里已经装了node.js然后才能采用以下命令(以下代码最好不要同时运行) sudo n - ...
- 【软件工程1916|W(福州大学)_助教博客】2019年上学期期末问卷调查结果公示
1.调查问卷概况 福州大学2019W班,收集到有效答卷44份 2. 调查问卷情况 Q1:请问你平均每周在课程上花费多少小时? 去除自估水平超过40小时的,平均16.6H Q2.软工实践的各次作业分别花 ...
- c:forTokens标签循环输出
对带有相同符合格式内容进行分割输出,例如,varstr="1,2,3,4,5,6"; c:forTokens属性说明表 引用 varStatus,它们描述了迭代的当前状态,如下这些 ...
- 你真的了解FastClick吗?
你真的了解FastClick吗? 前段时间在做公司官网手机端菜单部分的时候,遇到一些很诡异的点击问题.比如菜单点击无效/双击才有效.在手指滑动的时候会触发点击事件.以及同样的事件处理在微信跟浏览器会有 ...
- Redis面试题(46题)
1.什么是Redis?简述它的优缺点? Redis 的全称是:Remote Dictionary.Server,本质上是一个 Key-Value 类型的内存数据库,很像memcached,整个数据库统 ...
- [LeetCode] 875. Koko Eating Bananas 科科吃香蕉
Koko loves to eat bananas. There are N piles of bananas, the i-th pile has piles[i] bananas. The g ...
- [LeetCode] 145. Binary Tree Postorder Traversal 二叉树的后序遍历
Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...