es_倒排索引

目录

es, 倒排索引优点

新增修改数据

Segment合并

fsync和fdatafsync

创建索引的注意事项


es, 倒排索引优点

倒排索引是不可更改的,一旦它被建立了,里面的数据就不会再进行更改。这样做就带来了以下几个好处:

1. 不用给索引加锁,因为不允许被更改,只有读操作,所以就不用考虑多线程导致互斥等问题。

2. 索引一旦被加载到了缓存中,大部分访问操作都是对内存的读操作,省去了访问磁盘带来的io开销。

3. 倒排索引具有不可变性,所有基于该索引而产生的缓存也不需要更改,因为没有数据变更。

4. 倒排索引可以压缩数据,减少磁盘io及对内存的消耗。

 

新增修改数据

新增数据流程

  • 1.  文档数据写入到缓存
  • 2.1  translog(文档放在buffer的同时,都会把文档记录在translog中)
  • 2.2  refresh立即把缓存中的文档写入segment中(分片的refresh频率默认每秒1次,通过index.refresh_interval:100s参数控制,手动操作:curl -XPOST127.0.0.1:9200/_refresh)(如果要落地磁盘,需要使用fsync的操作来确保磁盘写入成功,这个过程是阻塞的,比较耗时,不使用 fsync 的方式落地磁盘)
  • 4.  segment写入文件系统缓存中(文件系统缓存中的数据可以被正常读取,ES利用这个特性,在segment被commit到磁盘之前,就打开对应的segment,这样存放在这个segment中的文档就可以立即被搜索到了)
  • 5.  当达到一定的时间间隔,或者translog足够大时,就会执行commit行为,将所有缓存中的segment写入磁盘。确保写入成功后,translog就会被清空。 (在es中可以通过_flush api进行手动触发,手动操作:curl -XPOST127.0.0.1:9200/tcpflow-2015.06.17/_flush?v)

每个commit point都会维护一个.del文件,

当一个文档删除时,首先会在.del文件内记录在某个segment内某个文档已经被删除。在segment中,被删除的文档依旧是能够被搜索到的,不过在返回搜索结果前,会根据.del把那些已经删除的文档从搜索结果中过滤掉。

当一个文档发生更新时,首先会在.del中声明这个文档已经被删除,同时新的文档会被存放到一个新的segment中。这样在搜索时,虽然新的文档和老的文档都会被匹配到,但是.del会把老的文档过滤掉,返回的结果中只包含更新后的文档。

lucene将一个大的倒排索引拆分成了多个小的段segment。

每个segment本质上就是一个倒排索引

在lucene中,同时还会维护一个文件commit point,用来记录当前所有可用的segment,当我们在这个commit point上进行搜索时,就相当于在它下面的segment中进行搜索,每个segment返回自己的搜索结果,然后进行汇总返回给用户。

 

Segment合并

每个segment都会占用独立的文件句柄/内存/消耗cpu资源,在查询的时候,需要在每个segment上都执行一次查询,这样是很消耗性能的。

es会自动定期的将多个小segment合并为一个大的segment,在segment合并的过程中,会自动将.del中的文档丢掉,从而实现真正意义上的删除操作。

当新合并后的segment完全写入磁盘之后,es就会自动删除掉那些零碎的segment,之后的查询都在新合并的segment上执行。

Segment的合并会消耗大量的IO和cpu资源,这会影响查询性能。

在es中,可以使用optimize接口,来控制segment的合并。

如:

POST/logtest-2021-01/_optimize?max_num_segments=1

这样,es就会将logtest-2021-01中的多个segment合并为1个。

对于那些更新比较频繁的索引,不建议使用optimize去执行分片合并,交给后台的es自己处理就好了。

 

fsync和fdatafsync

操作系统数据落地磁盘过程:

  • 数据首先保存在内存中
  • write 内存中的页缓存(page cache),更新到磁盘
  • 脏页面不会立即更新到磁盘中,而是由操作系统统一调度,如由专门的flusher内核线程在满足一定条件时(如一定时间间隔、内存中的脏页达到一定比例)将脏页面同步到磁盘上(放入设备的IO请求队列)。

fsync 的功能是确保文件fd所有已修改的内容已经正确同步到磁盘上,该调用会阻塞等待直到设备报告IO完成。

文件的尺寸(st_size)如果变化,是需要立即同步的,否则OS一旦崩溃,即使文件的数据部分已同步,由于metadata没有同步,依然读不到修改的内容。而最后访问时间(atime)/修改时间(mtime)是不需要每次都同步的,只要应用程序对这两个时间戳没有苛刻的要求,基本无伤大雅。

 fsync fdatasync 
io操作次数21
同步修改内容(脏页)
同步文件信息(metadata,包括size、访问时间st_atime & st_mtime等等)

Berkeley DB处理日志文件方式:

1.每个log文件固定为10MB大小,从1开始编号,名称格式为“log.%010d"

2.每次log文件创建时,先写文件的最后1个page,将log文件扩展为10MB大小

3.向log文件中追加记录时,由于文件的尺寸不发生变化,使用fdatasync可以大大优化写log的效率

4.如果一个log文件写满了,则新建一个log文件,也只有一次同步metadata的开销

创建索引的注意事项

es的倒排索引默认全部字段自动创建,创建索引的注意事项就是,不对那些字段进行创建

  • 不需要索引的字段,一定要明确定义出来,因为默认是自动建索引的
  • 同样的道理,对于String类型的字段,不需要analysis的也需要明确定义出来,因为默认也是会analysis的
  • 选择有规律的ID很重要,随机性太大的ID(比如java的UUID)不利于查询

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值