直接面试题走起
M:大概说一下ES底层的索引结构?
在一个节点或多个节点上形成index 每个节点上的index就是shard分片,每个分片相当于Lucene(full text Search Engine全文搜索库)的索引(shard=Lucene Index)
Mini index :segment 在Lucene Index里面有许多小部分segment,我们可以理解为是Lucene内部的小索引min_index。
然后segment的内部构造:
- Inverted Index倒排索引
- 一个有序的数字字典Dictionary(包括单词字段和单词出现的频率)如果是中文的话 就需要中文分词器了就是对应的中文词组和出现的频率
- 一个posting:与单词对应的文档id索引,就是对应单词在那些文档里出现过,做个记录,然后就能根据这个去那些文档里面搜索了
当我们搜索的时候,会首先对要搜索的内容进行分解分词,然后在字典里面找到对应的Term,从而查找对应的文档进行相关内容的搜索。
例如我们要搜索的内容是“pretty girl”:内容进行分解 有 pretty 和 girl 然后去dictionary里面去找对应的Term,再去posting里面去找对应的documents进行搜索。
思考:如果搜索内容和条件很复杂 我们如何去优化Term呢?因为我们要想高效必须避免全表扫描我们的dictionary
- 这个时候需要我们对搜索的内容进行优化操作 或者说是问题转化
- 后缀作为搜索条件时候,我们可以对Term进行反转,这样就变成前缀的搜索了;
- 对于GEO的地理信息,可以将对应的地理信息转化成GEO hash
- 对于简单的数字123类的,可以对应的生成多重的样式的Term
对于检查拼写错误
一个Python库为单词生成了一个包含错误信息的树形状态机,用于检测拼写错误。
-
Stored Fields
字段相当于mysql的column,顾名思义就是字段搜索,当我们要去搜索包含特定标题的内容的时候 这个时候Inverted index 就不能很好去处理了。
所以Lucene提供了另外一种数据结构去解决这个问题。本质上 Stored Field是一个键值对 默认条件下ES会存储整个文件的JSON source -
Docment Values
即使这样Lucene还是无法解决诸如排序,聚合,过滤,这样会获得很多我们不想要的信息
-
Cache
Lucene会将所有信息放进缓存,大大提高了它的查询效率。当我们使用ES搜索摸个文件document的时候,会相应的文件建立相应的缓存,并且refresh interval会定期每秒刷新这些数据
- 随着时间的推移,Elastic Search会产生很多segments,然后会进行相应的合并,并把不用的segments删除,这就是为什么有时候增加文件会使用索引占的空间变小,原因就是引起了合并merge,从而产生更多的压缩。
- segments是不可变的immutable当delete时候 只是将相应segment的标志位设置为删除,但是文件还是会在原来的位置,对于update本质上是,先把原来的segment标志位删除,然后re_index重新建立索引
- ES结点增加会进行re_index,这是非常消耗性能的,所以规划scale的时候尽量去避免结点数量变化
- 结点分配和shard分片的优化?可以根据数据的重要程度分配相应性能更好的硬件机器,尽量为每个shard都有对应的副本
- 路由routing,每个节点都有对应的路由表,当请求到达某个节点时候,这个节点都有将转发发到它期望的节点上去进一步处理。
一个真实的请求
- Query: 有两个字段,filtered和query
- Aggregation聚合:聚合的结果字段名是author_id,然后是聚合10条,相当于top10;搜索条件是根据author_id的size也就是点击数来排序,然后从100个分片中取10条
- 上帝节点:这个节点就是当前请求的协调者,由他决定:
- 根据索引信息,判断会路由到那个核心节点上以及那些副本是可用的等
- 把Query转成Lucene Query,进行分词过滤什么的,然后在索引里所有segment里进行搜索
M: 在建立ES搜索结构时候 跟关系型数据库的库名 表名 以及字段名 那些是对应起来的?
SQL型数据库 | Elastic Search |
---|---|
DataBase | index |
table | type |
row | docment |
cloumn | feild |
schema | mapping |
M: ES除了ELK还可以用来做那些事情?简单说说?
平常我们开发主要是对中文进行搜索,所以需要安装中文分词器中文分词器ik下载地址
然后在es的安装目录下的plugins下新建一个ik的目录,将zip包解压到该目录下重启es即可~详细参考
@Data// lombok
@Document(indexName = "databaseName",type = "table")
public class News implements Serializable {
private Long id;
// 这里可以对分词器进行配置
@Field(type= FieldType.Text,analyzer = "ik_max_word")
private String title;
private String content;
}
然后就可以CRUD了