elasticsearch原理学习

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

 

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

 

lucene1.4文档翻译整理:

 

Lucene基本的概念包括 Index 、 document、field、term

一个index包含一个文档序列
一个文档包含一个field序列
一个field包含一个命名的term序列
一个term就是一个字符串

在不同field中的相同字符串被人为是不同的term

所以term被认为是一个字符串对,第一个是field的名字,第二个是field的text值

index存储了term相关的统计数据,以便于基于term的查询更加高效,lucene的索引类似于被称为倒排索引的索引格式(inverted index),

一个Field可能被正向存储在index literally中,也可能被倒排索引到索引文件中

field的text可能被分词以后被索引,也可能不分词就被索引

索引可能包含多个字索引,或者称为segment,每个segment是一个完全独立的index,索引动作可能由新加文档和合并已经存在segment时触发。

一个搜索动作可能设计多个segment的搜索

documentID是顺序分配的,但是ID只是在一个segment内唯一,当merge segment或者删除无用文档时,可能会修改documentID

每个segment包含:
Field names
Stored Field values 对于每个文档会存储一个attr:value的映射列表,这个跟结构化数据差不多,这个数据用于在搜索的时候根据documentID拉取数据使用。
Term dictionary 保存了所有用到的term以及包含该term的文档编号和指向该term频率和相似度数据的指针
Term Frequency data 按照term纬度存储,每个term数据有包含该term的文档编号列表以及每个文档中包含该term的频率
Term Proximity data 保存了每个term在每个文档出现的位置
Normalization factors 静态数据,每个doucument中的每个field都会存储一个这个值,这个值后面会用来乘上这个field命中的分数。 不知道这个是干啥用的,说的也不清楚???
Term Vectors 存储粒度每个文档每个field,存储的数据为term的text和term frequency
Deleted documents 存储已经删除的文档

文件名说明:
一个index下的所有文件都在一个文件夹中,一个segment下的所有文件都有相同的前缀。
基础类型:
Byte 字节。 是最基础的类型,所有其他数据类型都是Byte字节序。
UInt32 4字节
Uint64 8字节
VInt 变长度Int,每个字节的第一位表示后面是否还有字节,所以从前往后读,可以根据读的字节的第一位来界定这个Vint的长度,每个字节去掉第一位还剩下7位存储数据,按照字节从后往前,把每个字节剩下的7位拼接起来,就是最后的值。例如:十进制的16385,存储Vint为 10000001 10000000 000000001,第一个字节第一位1表示后面还有字节要读,第二个字节第一位为1表示后面还有字节要读,第三个字节第一位为0表示后面没有字节要读了,所以可以判断这个Vint有三个字节,下面开始拼接,从最后一个字节开始,去掉每个字节的第一位,可以得到 0000001 0000000 0000001 ,然后把这个二进制序作为最后的值就是16385
Chars UTF-8编码的字符
String 格式为Vint + Chars,从一个Vint标示这个String有多少长(字节还是字符?)然后后面是Chars
索引级别文件:
Segment File:文件名为segments。 每个索引只有一个这个文件,里面存储的是该索引所有的segment列表,格式为 Format/Version/SegCount,<SegName,SegSize> * SegCount,Format/SegCount/SegSize都是Uint32类型,Version是UInt64类型,SegName是String类型,在lucene1.4中Format为1,Version记录了该Index被修改了多少次,修改包括增加、删除文档,SegSize是这个segment中有多少document
Lock Files: Index里有一些文件用于标示当前索引正在被其他索引在使用,这些文件存储在系统配置 java.io.tmpdir中。
commit.lock:
When a file named "commit.lock" is present, a process is currently re-writing the "segments" file and deleting outdated segment index files, or a process is reading the "segments" file and opening the files of the segments it names. This lock file prevents files from being deleted by another process after a process has read the "segments" file but before it has managed to open all of the files of the segments named therein.
commit.lock文件没有理解是如何工作的
write.lock: 当这个文件存在时表示当前正在有个进程在添加或者删除文档,这个文件禁止多个进程同时修改索引。
Deletable File: 文件名为: deletable, 这个文件中存储了没有使用但是不能删除的文件,Deletable File只在Win32系统中使用,在其他操作系统中这里是空,Deletable的格式为 DeleteableCount,<DelableName>*DeleteableCount,DeletableCount为Uint32类型,DeletableName为String类型
段级别文件:
Fields:文件名后缀为 .fnm,格式为FieldsCount,<FieldName,FieldBits> * FieldsCount,FieldsCount为VInt类型,FieldName为String类型,FieldBits为Byte类型,FieldBits最后一位为1表示索引Field,为0表示不索引字段,倒数第二位为1表示存储了term vectors(还不知道term vectors是什么?),0表示没有存储term vectors,Fields的编号根据它们在这个文件中的顺序决定,第一个为0,第二个为1,以此类推。field的编号和document一样,是在当前segment范围内的
Stored Fields:
.fdx: 存储文档到该文档field数据的指针,格式为 <FieldValuesPosition>*SegSize,FieldValuesPosition类型为Uint64,通过文档ID查询Fields的方法是拿文档ID * 8即为该文档Field数据的索引。
.fdt: 这个文件存储了每个文档的field值,格式为: <DocFieldData>*SegSize,DocuFieldData格式为FieldCount,<FieldNum,Bits,Value>*FieldCount,FieldCount:Vint;FieldNum:VInt;Bits:Byte;Value:String。目前Bits只用到最后一位。为1表示是一个需要分词的字段,为0表示非分词字段。
Term Decitonary文件:
tis: 存储term信息,所有term先按照该term所属field的name字典排序,然后在按照term的text排序,文件格式为:
TermInfoFile(.tis) --> TIVersion,TermCount,IndexInterval,SkipInterval,TermInfos
TIVersion指定该文件的版本
TermCount指定该文件存储了多少个term
IndexInterval ??
SkipInterval这个猜测应该是存储跳表的间隔 ??
TermInfos存储所有的Term,按照上面所说的顺序排序存储,TermInfos的格式为 <TermInfo> * TermCount
TermInfo的格式为 --> <Term,DocFreq,FreqDelta,ProxDelta,SkipDelta>
Term存储的是term的信息,后面再说
DocFreq存储的是该Term有多少个文档包含了该Term
FreqDelta 存储的是该Term的TermFreqs数据在.frq文件中的位置
ProxDelta 存储的是该Term的TermPositions数据在.prx文件中的位置,这个TermPositions数据是干啥用的??
SkipDeltaDelta 存储的是该Term的SkipData在.frq文件中的位置,因为frq文件已经存储了上面说的TermFreqs数据,而这个SkipData是存储在TermFreqs数据后面的,一一对应,所以SkipDelta存储的其实是TermFreqs的长度,要是找SkipData,则先找到对应的TermFreqs,然后加上该SkipDelta就是SkipData的值。
Term的格式为:<PrefixLength,Suffix,FieldNum>
PrefixLength和Suffix是搭配使用,PrefixLength是相对于当前Term的前一个Term来计算出来的,就是当前term相对于前一个term前缀相同的长度,比如有两个term: bone、boy,则后一个boy这个term的PrefixLength就是2
Suffix就是去除PrefixLength指定的前缀以后的term值,比如上面说的bone和boy,那boy的Suffix就是y
FieldNum就是这个term对应的Field的fieldNum
tii: 这个文件和tis非常相似,该文件的目的是将tis中的数据读入内存中,并提供对tis文件的随机访问。
格式: IndexTermCount,TermIndices
IndexTermCount

 

转载于:https://www.cnblogs.com/caiyao/p/11205311.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值