1、ES基础概念
搜索引擎 search engine
近实时 (Near) Real Time Search
RESTful API
分布式,高可用性
存储文档,json格式
基于Apache Lucene
2、核心概念
Cluster 集群
Node 单机节点构成集群
Index 索引
Shard 分片
Replica 副本
Segment 分段
Document 文档
Field 字段
Inverted Index 倒排索引
Text / Keyword 类型
使用全过程
schema(mapping)
es不需要前面的schema定义,在索引中doc时确定schema
因为es数据的交互形式是json,所以doc可开箱即用,写入doc如果没有预定义,则没有预定义mapping,doc的每一个field根据传来的json数据确定类型,默认规则(dynamic field mapping)如下:
json类型 |
es类型 |
null |
不会增加field |
boolean |
boolean |
string |
date(通过Date detection)double/long (通过Numeric detection)text(带keyword的sub field) |
number |
float/long |
object |
Object |
array |
array(array的item类型取决于第一个非null元素类型) |
同时es还支持定义模板 dynamic_template,扩大和修改默认规则,如下例所示,修改默认规则string映射:
{ "mappings": { "dynamic_templates": [ { "strings_as_keywords": { "match_mapping_type": "string", "mapping": { "type": "text" } } } ] }
如果不需要动态字段,则不建议使用es的dynamic mapping,使用不当会造成污染mapping,因此可以指定 dynamic为false来关闭动态mapping。
当然可以用put mapping api来预定义index的mapping结构包括字段类型和使用的分析器(text类型)、索引等。
es官方也强烈建议以不同的方式索引相同的字段es例如,一个字符串类型的值可以通过索引形成text全文检索的类型也可以索引keyword排序和聚合类型。
建议使用别名(alias),es对mapping扩张是开放的,但对mapping禁止修改。例如,可以mapping增加一个字段,但是不能删除/修改字段。所以使用alias指向真正的index,这样,在有field可以使用需要修改的场景reindex api重建索引,重复使用alias api改变方向,实现无缝切换。
数据写入
分布式写入过程
可以看到,es写入的总延迟等于写入主节点的时间 max(从节点写入时间)。
Shard 写入流程
三个更重要的概念
refresh
flush
fsync todo:是否会丢失数据
写入优化
使用bulk api批量操作
调整refresh_interval的间隔,es在每一次refresh时都会创建lucene的segment,并尝试进行segment合并,成本大,如果实时搜索要求不高,可以适当调整refresh_interval的大小
指定不需要索引的字段index属性为not_analyzed
SSD(经典性能不好,硬件来凑)
读取
Search
使用search api可以很方便的实现数据的检索。es提供了很多search api,例如match_query,term_query等等,组装起来很方便query DSL(Domain Specific Language),开发人员不需要考虑DSL中query的顺序,dsl中query顺序不会影响最终的执行效率,实际执行顺序将在CBO(Cost Based Optimizer)重排后进行。
term index 使用FST(Finite State Machines) -> 定位倒排链
SkipList -> 合并倒排链
Aggregation
Metrics 将query命中的数据集count,max等待操作是一个单一的值
Bucket 将query命中的数据集按条件分为较小的数据集,然后在这些小集中执行Metrics,可以类比于sql中的group by
Sort
不要使用text字段作为排序字段,text字段一般用分析器分词text字段排序往往得不到预期的结果
ES返回的doc默认会按照_score(文档相关性)降序排列,即计分后的分数值,如指定其他分数Sort根据指定的字段对字段进行排序。同样支持script,构建复杂的排序规则。
_score,评分的计算取决于不同的query例如,方法fuzzy查询会计算与检索词拼写的相关性,term查询会计内容与关键词之间的百分比等。但是一般意义上我们说的全文搜索是指计算内容与关键词的相关程度,ElasticSearch使用相似度算法 TF/IDF,即词频/逆文档频率包括以下内容:
词频:检索词出现在这个字段中的频率。频率越高,相关性越高。字段中出现5次的相关性高于只出现1次。
逆文档频率:索引中每个检索词的频率。频率越高,相关性越低。检索词出现在大多数文档中的权重低于出现在少数文档中的权重, 也就是说,检验文档中检索词的普遍重要性。
字段长度标准:字段的长度是多少?长度越长,相关性越低。短时间内出现检索词 title 出现在一个比同一个词长的词 content 字段相关性较高。
Page
1.基于offset的分页
from size,from指定偏移量,size指定要取的数据条数
执行原理:
client发起请求,收到请求shard负责合并后续请求数据的协调节点
执行query,取到from size大小结果集,协调节点本地建设大小from size的prioity queue ,协调节点将请求分发到其他shard
其他shard 同样执行query,取到from+size大小的结果集,将集合返给协调节点
协调节点合并结果集,最后得到from+size大小的priority queue,将后size个数据返给client
特点:支持随机分页访问 不适合用在feed无限下拉场景,在分页的边界可能存在数据重复的可能性 随着from的增大,开销也逐渐增大,不适合深度分页的场景
2.基于cursor的分页 scroll
针对这次请求将符合条件的所有结果汇集到协调节点缓存起来,后续直接从协调节点的缓存中取出
由于缓存的存在,文档后续的变更并不会同步到缓存中,并不适合实时请求
同样因为缓存的数据量为query命中的所有doc,所以scroll的堆内存开销是非常大的
适用于索引的重建/数据的迁移等非实时、低频的场景
3.search_after
使用上一页的检索结果来帮助检索下一页,排序字段里要包括doc的唯一标识,以保证search_after的一致性
每一个shard请求的数据集大小为size
不支持随机分页访问
实时处理,若doc有变更且影响到了排序因子,有可能出现重复数据
读取优化
没有范围查找需求的number类型字段,类型定义为keyword
慎用wildcard query,尽量使用分词后的结果使用match query,有使用wildcard query的需求,注意字符转义
搜索词的长度要做限制
feed流场景使用search_after
不需要得分的字段用filter context替换query content,query和filter区别
IT技术分享社区
个人博客网站:https://programmerblog.xyz
文章推荐程序员效率:画流程图常用的工具程序员效率:整理常用的在线笔记软件远程办公:常用的远程协助软件,你都知道吗?51单片机程序下载、ISP及串口基础知识硬件:断路器、接触器、继电器基础知识