转自:jianshu.com/p/883325b7bbda
众所周知,ES 中 filter 是不参与相关性评分的,所以查询子句可以被系统进行缓存,性能要高于普通的 query 查询。bool 查询中支持 4 种子句,分别是 filter、must、must_not、should,其中 filter 和 must_not 属于过滤器,过滤器查询先于其它查询执行。另外在 function_score、constant_score 中也可以使用 filter 子句进行查询缓存。
indices.memory.index_buffer_size 默认是 jvm 大小的 10% ,将该值调大到 20%,经常查询的索引分片数据会被缓存,当该值足够大时缓存的数据就会更多,查询就会更快。
增加 Index Refresh 间隔,目的是减少 Segment Merge 的次数,建议设置为 30s-90s 定期将只读或写少的索引进行 segment 合并,降低 segment 数量对搜索性能提升帮住很大,合并过程中将 only_expunge_deletes 设置为 true 意思是将标记为删除的数据清除掉。
curl -XPOST "http://host/visitor/_forcemerge?only_expunge_deletes=true&max_num_segments=1&flush=true"
SearchType 默认是 QUERY_THEN_FETCH,可在查询时指定为 dfs_query_then_fetch,这样协调节点只需要请求一次数据节点就可以完成请求处理了。
QUERY_THEN_FETCH:ES 默认的搜索方式。
第 1 步,先向所有的分片发请求,各分片只返回文档的相似度得分和文档的 ID,然后协调节点按照各分片返回的分数进行重新排序和排名,再取出需要返回给客户端的 Size 个文档 ID。
第 2 步,在相关的分片中取出文档的详细信息并返回给用户。
QUERY_AND_FETCH:协调节点向所有分片发送查询请求,各分片将文档的相似度得分和文档的详细信息一起返回。然后,协调节点进行重新排序,再取出需要返回给客户端的数据,将其返回给客户端。由于只需要在分片中查询一次,所以性能是最好的。
DFS_QUERY_THEN_FETCH:与 QUERY_THEN_FETCH 类似,但它包含一个额外的阶段:在初始查询中执行全局的词频计算,以使得更精确地打分,从而让查询结果更相关。
QUERY_THEN_FETCH 使用的是分片内部的词频信息,而 DFS_QUERY_THEN_FETCH 使用访问公共的词频信息,所以相比 QUERY_THEN_FETCH 性能更低。
DFS_QUERY_AND_FETCH:与 QUERY_AND_FETCH 类似,不过使用的是全局的词频。
/_search?preference=abcd&search_type=dfs_query_then_fetch #preference 可以确保字符串标识相同时,每次请求会发送到相同的分片执行
ES 6.x 之后新增预排序功能,即索引在创建之前可以指定数据写入后的排序方式,当 query 时指定的排序方式和预排序逻辑一致时将能够很快获得排序结果,需要注意的是 查询时不能开启 total 值
{
"settings": {
"index": {
"sort.field": [ "username", "date" ],
"sort.order": [ "asc", "desc" ]
}
},
"mappings": {
"properties": {
"username": {
"type": "keyword",
"doc_values": true
},
"date": {
"type": "date"
}
}
}
}
{
"size": 10,
"sort": [
{ "username": "asc" },
{ "date": "desc" }
],
"track_total_hits": false
}
有条件的尽量使用 SSD 盘,或者挂载多块盘提升 io 性能,以下是不同磁盘在并发场景下的性能表现:
在有聚合分析场景的业务需要单独指定高配服务器用于聚合查询,与现有点查服务进行隔离;一般要求 CPU 在 16 核以上
# 查询聚合节点配置(conf/elasticsearch.yml):
node.master:false
node.data:false
node.ingest:false
如果不需要精确统计查询命中记录条数,可以配 teminate_after 指定每个 shard 最多匹配 N 条记录后返回,以及设置查询超时时间 timeout 使得请求提前结束
{
"timeout": "10s",
"terminate_after": 1000,
"query": {
}
}
默认深度优先聚合改为广度优先聚合。
"collect_mode" : "breadth_first"
depth_first 直接进行子聚合的计算
breadth_first 先计算出当前聚合的结果,针对这个结果在对子聚合进行计算。
一般应用在操作时序日志的场景, 通过定义模板动态生成索引,如将超出 3 个月的索引通过定时任务归档到 cold 组 ,具体操作如下:
1、将 data node 划分为冷热数据节点
# cat elasticsearch.yml // 配置文件设置tag区分
node.attr.tag: cold/hot
# bin/elasticsearch -d -Enode.attr.box_type=hot //启动设置
2、根据模板按月生成索引,格式如 visitor_2019-01
#构建索引模板,滚动新增的索引将按照模板进行创建
curl -X PUT "localhost:9200/_template/visitor" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["visitor_*"],
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.routing.allocation.include.tag" : "hot"
},
"mappings": {}
}
'
3、归档历史数据到 cold 节点
curl -X PUT "${es}/${i}/_settings" -H 'Content-Type: application/json' -d'{
"number_of_replicas": 0,
"index.routing.allocation.include.tag": "cold"
}'
其它配置说明
可以用半角逗号隔开设置的多个存储路径,在多硬盘的服务器上设置多个存储路径是很有必要的。