es搜索核心与实战Day07

    技术2022-07-11  132

    es搜索核心与实战Day07

    1.文档到分片的路由算法

    shard=hash(_rounting)%number_of_primary_shards

    ​ Hash算法确保文档均匀分散到分片中

    ​ 默认的_routing 值是文档id

    ​ 可以自行制定routing数值,例如用相同国家的商品,都分配到指定的shard

    ​ 设置Index Setting后,Primary数,不能随意修改的更本原因

    更新一个文档

    2.分片及其生命周期

    a.倒排索引的不可变性

    倒排索引采用Immutable Design,一旦生成,不可更改不可变性,带来了的好处如下:

    ​ 1.无需考虑并发写文件的问题,避免了锁机制带来的性能问题

    ​ 2.一旦读入内核的文件系统缓存,便留在哪里。只要文件系统存有足够大的空间,大部分请求就会直接请求内存,不会命中磁盘,提升了很大的性能

    ​ 3.缓存容易生成和维护/数据可以被压缩

    3.什么是Refresh

    将Index buffer写入Segment的过程叫Refresh。Refresh不执行fsync操作Refresh频率:默认1秒发生一次,可通过index.refresh_interval配置。Refresh后,数据就可以被搜索到。这也是为什么Elasticsearch被称为近实时搜索如果系统有大量的数据写入,那就会产生很多的SegmentIndex Buffer被占满时,会触发Refresh,默认值是JVM的10%

    4.什么是Transaction Log

    Segment写入磁盘的过程相对耗时,借助文件系统缓存,Refresh时,先将Segment写入缓存以开放查询为了保证数据不会丢失。所以在Index文档时,同时写入Transaction Log,高版本开始,Transaction Log默认落盘。每个分片有一个Transaction Log在ES Refresh时,Index Buffer被清空,Transaction Log不会清空

    5.什么是Flush

    ES Flush&Lucene Commit

    ​ 调用Refresh,Index Buffer清空并且Refresh

    ​ 调用fsync,将缓存中的Segments写入磁盘

    ​ 清空(删除)Transaction Log

    ​ 默认30分钟调用一次

    ​ Transaction Log满(默认512MB)

    6.Merge

    Segment很多,需要被定期合并

    ​ 减少Segments/删除已经删除的文档

    ES和Lucene会自动进行Merge操作

    ​ POST my_index/_forcemerge

    7.剖析分布式查询及相关性算分

    1.Query阶段

    用户发出搜索请求到ES节点。节点收到请求后,会以Coordinating节点的身份在6个主妇分片中随机选择3个分片,发送查询请求被选中的分片执行查询,经行排序。然后,每个分片都会返回From+Size个排序后的文档Id和排序值给Coordinating节点

    2.Fetch阶段

    Coordinating Node会将Query阶段,从每个分片获取的排序后的文档Id列表,重新进行排序。选取From到From+Size个文档的Id以multi get请求的方式,到相应的分片获取详细的文档数据

    3.Query Then Fetch潜在的问题

    性能问题

    ​ 每个分片上需要查的文档个数=from+size

    ​ 最终协调点需要处理:number_of_shard*(from+size)

    ​ 深度分页

    相关性算分

    每个分片都基于自己的分片上的数据经行相关度计算。这会导致打分偏离的情况,特别是数据很少时。相关性算分之间是相互独立。当文档总数很少的情况下,如果主分片大于1,主分片数越多,相关性算分会越不准

    4.解决算分不准的方法

    数据量不大的时候,可以将主分片数设置为1

    ​ 当数据量足够大时侯,只要保证文档均匀分散在各个分片上,结果一般就不会出现偏差

    使用DFS Qurery Then Fetch

    ​ 搜索的URL中指定参数“_search?search_type=dfs_query_then_fetch”

    ​ 到每个分片把个分片的词频和文档频率进行搜集,然后完整的进行一次相关性算分,耗费更多的CPU和内存,执行性能低下,一般不建议使用

    POST message/_doc { "content":"good" } POST message/_doc { "content":"good morning everyone" } POST message/_doc { "content":"good morning" } POST message/_search { "query": { "term": { "content": { "value": "good" } } } } DELETE message PUT message { "settings": { //20个分片算分一样 "number_of_shards": 20 } } GET message POST message/_doc?routing=1 { "content":"good" } POST message/_doc?routing=2 { "content":"good morning" } POST message/_doc?routing=3 { "content":"good morning everyone" } POST message/_search { "explain": true, "query": { "term": { "content": { "value": "good" } } } } //type dfs_query_then_fetch POST message/_search?search_type=dfs_query_then_fetch { "query": { "term": { "content": { "value": "good" } } } }

    8.排序及DocValues&Fielddata

    1.排序

    //单字段排序 POST /kibana_sample_data_ecommerce/_search { "size":5, "query": { "match_all": { } }, "sort": [ { "order_date": { "order": "desc" } } ] } //多字段排序 POST /kibana_sample_data_ecommerce/_search { "size":5, "query": { "match_all": { } }, "sort": [ { "order_date": {"order":"desc"}}, {"_doc":{"order": "asc" }}, {"_score":{"order": "desc"}} ] } //对text排序报错 POST /kibana_sample_data_ecommerce/_search { "size":5, "query": { "match_all": { } }, "sort": [ { "customer_full_name": { "order": "desc" } } ] } //打开text的 fielddata PUT kibana_sample_data_ecommerce/_mapping { "properties":{ "customer_full_name":{ "type":"text", "fielddata":true, "fields":{ "keyword": { "type":"keyword", "ignore_above":256 } } } } }

    2.排序的过程

    排序是针对字段原始内容进行的。倒排索引无法发挥作用需要用到正排索引。通过文档Id和字段快速得到字段原始内容Elasticseach有两种实现方法

    ​ 1.Fielddata

    ​ 2.Dov Values(列式存储,对Text类型无效)

    关闭Dov Values

    默认启用,可以通过Mapping设置关闭

    增加索引的速度/减少磁盘空间

    如果重新打开,需要重建索引什么时候需要关闭
    Processed: 0.012, SQL: 9