ES的检索原理

269 阅读2分钟

物理结构

Shard-Segment Shard-Segment

每个segment中包含

  1. Inverted Index
  • a. 一个有序的数据字典 Dictionary(包括单词 Term 和它出现的频率)。
  • b. 与单词 Term 对应的 Postings(即存在这个单词的文件)
  1. Stored Fields 单独把指定Field拉出来存储,查询时取值速度快,一般在从_source中获取代价比较大时指定(获取10个feild值是从_source中获取1个的10倍)
  2. Document Values
  3. Cache 动态索引

内存中加载Term index,硬盘存储Term字典+倒排表 image.png 实际上lucene的Term index采用了FST变种的trie树,既能前缀匹配也能后缀匹配,而且大大节省了空间

索引过程

image.png

image.png

如上图所示,为一个节点索引文档的流程:

  1. elasticsearch节点接收index请求,存入index buffer,同步存入磁盘transationlog后返回索引结果
  2. Refresh定时将index buffer数据生成segment,存入到操作系统缓存,此时没有fsync,清空indexbuffer,此时就可以被elasticsearch查询了,如果index buffer占满时,也会触发refresh,默认为jvm的10%。
  3. Flush定时将缓存中的segments写入到磁盘,删除transactionlog。如果transactionlog满时(512m),也会触发flush。
  4. 如果数据很多,segment的也很多,同时也可能由删除的文档,elasticsearch会定期将它们合并。

检索过程

  1. 内存加载的Term Index结构
1级2级3级
索引2023-03-01Shard1Term Index
索引2023-03-01Shard2Term Index
  1. 查询以索引为维度,在内存中匹配所有Shard的Term index的Trie,再去命中的Shard中的Dictionary和Posting List找到doc id,再去读doc。

Lucene 索引文件结构主要的分为:词典、倒排表、正向文件、DocValues等,如下图:

优化方法

ES写入优化

  1. 客户端优化:bulk批量操作,
  2. 清洗优化:Kafka削峰,部分场景丢弃_source,不存储非必要的大字段
  3. 服务端优化:
  • tranlog:异步
  • refresh优化:间隔、分词算法ik_smart、hanlp,设置字段不分词(type=keyword)
  • 系统缓存:加内存、刷到ssd硬盘、量大的索引写入到同一集群
  • merge:ssd、merge线程数、merge流量限制
  • 副本同步:减少副本数

ES查询优化

query->filter …… shard数 数据层优化:数据切分