es优化 动态索引 json写法 script 聚合

es 高亮只是让结果更新意 new HighlightBuilder.Field(knowledgeTitleFieldName).preTags(preTags).postTags(postTags);
权重搜索
FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery(“type”, 3), ScoreFunctionBuilders.weightFactorFunction(100)),
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery(“type”, 2), ScoreFunctionBuilders.weightFactorFunction(1)),
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery(“type”, 1), ScoreFunctionBuilders.weightFactorFunction(1))
};
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery(“userId”, 1));
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQuery, filterFunctionBuilders);
searchSourceBuilder.query(functionScoreQueryBuilder)
.sort(“_score”, SortOrder.DESC)
.sort(“heat”, SortOrder.DESC);

analyzer分词器 内置
IK分词器有两种分词模式:ik_max_word详细模式和 ik_smart 粗略模式
自定义扩展词库 config目录下,新增自定义词典 ext_dict.dic 把自定义的扩展词文件添加到IKAnalyzer.cfg.xml中 停用词典 同义词典
全文
相对于matchQuery,multiMatchQuery针对的是多个field
searchSourceBuilder.query(QueryBuilders .multiMatchQuery(keyword, “author”,“content”,“title”));
queryStringQuery matchAllQuery匹配所有文档

集群 选举
集群名称一样,node不一样 节点类型 cluster_init数组节点
master、data(数据节点)、Coordinating(协调节点)、Ingest(预处理节点)。
ZenDiscovery是ES自己实现的一套用于节点发现和选主等功能的模块discovery.zen.ping.unicast.hosts
总结一句话,即当一个节点发现包括自己在内的多数派的master-eligible节点认为集群没有master时,就可以发起master选举。 ping方式 顺序投票 得到过半的票选举成功

同一个文档冲突
partial update内部会自动执行我们之前所说的乐观锁的并发控制政策 修改版本号_version都会新增
retry策略

  1. 再次获取document的数据和最新版本号
  2. 基于最新版本号再次去更新,如果成功就ok
  3. 如果失败了,重复1和2俩个步奏,最多重复的次数可以通过retry那个参数的值指定,比如5次

优化 参数设置
字段属性更精准,text分词,keyword不分词
分片 一个share寸10g-50g,20亿条数据 分片数 节点数n(1.5-3)
动态index 按月份 加*查询所有或者别名
if(!elasticsearchTemplate.indexExists(student.getClass())){
elasticsearchTemplate.createIndex(student.getClass());
elasticsearchTemplate.putMapping(student.getClass());
}

就是你的机器的内存,至少可以容纳你的总数据量的一半!!! filesystem cache 的就是每台机器才 一半
128g 缓存64g 总数据量可以达到128g,相当于3个分片嘛!!!!!!!!!!!
数据预热:,经常会有人访问的数据,最好做一个专门的缓存预热子系统,就是对热数据每隔一段时间,就提前访问一下,让数据进入 filesystem cache 里面去。!!!!
冷热分离:最好是将冷数据写入一个索引中,然后热数据写入另外一个索引中 插入后后续分析!!version判断多少次

节点属性 协调节点可以使大型集群受益。它们加入集群并监视完整的集群状态,就像其他每个节点一样,它们使用集群状态将请求直接路由到适当的节点。
参数设置 jvm优化在这里插入图片描述
trie树只共享了前缀,而 FST 既共享前缀也共享后缀,更加的节省空间
由于Segment不可修改,更新被看成是删除+新增两个操作。即会将旧的文档在.del文件中标记删除,然后文档的新版本被保存到一个新的Segment中。 不需要锁,设计简单,读写性能高。

Tomcat。在这种情况下,多个Web应用程序可以共享一个JVM。
一个服务就是一个jvm实例!!!!!!

batched_reduce_size参数可以不等待全部分片返回结果,而是在指定数量的分片返回结果之后就可以先处理一部分reduace这样可以避免协调节点在等待全部结果的过程中占用大量内存,避免极端情况下可能导致的OOM

GC (Allocation Failure)造成的young gc。Allocation Failure表示向young generation(eden)给新对象申请空间,但是young generation(eden)剩余的合适空间不够所需的大小导致的minor gc。
年轻代垃圾回收器ParNew(多线程 标记整理) 老年代垃圾回收器CMS(标记清理)

写入过程 translog -> mem buffer -> refresh -> segment文件缓存中(os cache) ->fsync -> os disk

xmx不超过内存的50 要留给文件系统缓存
新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor
–XX:NewRatio 默认1:2
–XX:SurvivorRatio 默认的Eden : from : to = 8 : 1 : 1

Minor GC发生:当jvm无法为新的对象分配空间的时候就会发生Minor gc
Full GC:发生GC有两种情况,当老年代无法分配内存的时候 持久代空间不足 显示调用System.gc

-XX:MaxTenuringThreshold=15表示当对象的存活的年龄(minor gc一次加1)大于多少时,进入老年代 es好像是6

如果满足下面的指标,则一般不需要进行GC优化:!!!
Minor GC 执行时间不到50ms
Minor GC 执行不频繁,约10秒一次
Full GC 执行时间不到1s
Full GC 执行频率不算频繁,不低于10分钟1次 6319616 5242880

ElasticsearchStatusException[Elasticsearch exception [type=search_phase_execution_exception, reason=all shards failed]]
“reason”:{“type”:“exception”,“reason”:"Trying to create too many scroll contexts. Must be less than or equal to: [500]
一次分页都是同一个scroller来操作的
curl -u elastic:jw_1qazZAQ! –X DELETE ‘localhost:9200/_search/scroll/_all’

es优化:scrollid优化!!!
1.前端虚化
2.抛弃浅分页 from+size 用scrollid
3.scrollerid报错 一次查询有时候有18个产生 加大个数,减少过期时间 异常后正确清理scrollerid
4.有一次es报错,查看日志/var/log/es,通过查看_nodes_stat发现scrollerid没正确被清理,最大500个

修改scroll最大
curl -x “” -X PUT localhost:9200/_cluster/settings -H ‘Content-Type: application/json’ -d’{
“persistent” : {
“search.max_open_scroll_context”: 1024
},
“transient”: {
“search.max_open_scroll_context”: 1024
}
}’

修改最大查询的限制
_all/_settings
{
“index.max_result_window”:200000
}

https://blog.csdn.net/marvin198801/article/details/123413906
postman http://:9200/_nodes/stats?pretty scroll_current
delete http://:9200/_search/scroll/_all 删除scrollid

分页查询的过程 web 搜索引擎对任何查询都不
要返回超过 10000 个结果的原因 需要设置! max_result_window 时,es 将返回错误
from size 4个主分片的索引中搜索,每页返回10条记录 协调节点对 40 个结果排序得到全部结果的前 10 个
当我们请求第 99 页(结果从 990 到 1000),需要从每个分片中获取满足查询条件的前1000个结果,返回给协调节点, 然后协调节点对全部 4000 个结果排序,获取前10个记录。

Scroll API 原理上是对某次查询生成一个游标 scroll_id, 后续的查询只需要根据这个游标去取数据
查询的相应数据是非实时的 建立了一个临时的历史快照,在此之后的增删改查等操作不会影响到这个快照的结果
srcoll_id 的存在会耗费大量的资源 用完之后要及时清理

PIT + search_after 不能够随机跳转分页,只能是一页一页的向后翻 官方不支持前向翻页:ES中的向前翻页问题可以通过翻转排序方式来实现!!!
PIT的本质:存储索引数据状态的轻量级视图 某个指定条件的位置! 相当于就是把条件结果保存为一个临时视图
search_after 参数使用上一页中的一组排序值来检索下一页的数据,查询仅支持向后翻页。

业务层面优化 百度搜索的分页最多只能到 76 页
1.增加默认的筛选条件 减少满足条件的数据量,避免出现深度分页的情况。
2.分页虚化,禁止大范围跳页 末尾查询评分非常低!!的结果一般参考意义都不大。

ES中,搜索一般包括两个阶段,query 和 fetch 阶段。可以简单的理解,query 阶段确定要取哪些doc,fetch 阶段取出具体的 doc
各个分片返回给 coordinating node doc 的_id以及用于排序的_score即可,这样也可以保证返回的数据量足够小。!!!
DFS类型适合微调 精度高,但是搜索的效率低
query then fetch 默认 只在分片进行打分(TF-IDF 出现频率)
dfs query then fetch 多了一个初始化散发(initial scatter)计算全局词频(term frequencies)步骤 全局进行打分
query and fetch 查询方法只需要去shard查询一次 但是内存很大 返回的时候把元素文档(document)和计算后的排名信息一起返回 搜索方式是最快的
dfs query and fetch

es动态索引

org.springframework.boot
spring-boot-starter-data-elasticsearch

@Document(
indexName = “student-” + “#{ T(com.river.es.entity.Student).dateStr() }”,
shards = 2,
createIndex = true,//默认会去createIndex和putMapping!!!
replicas = 1, refreshInterval = “-1”)

public static String dateStr(){
return LocalDate.now().toString(); //年月日
}

模板方法curd testRepository.save(student);动态保存
public interface TestRepository extends ElasticsearchRepository<TestStudent, String> {

查询所有index加* !! 还可以所有数据写别名 然后读别名读到所有索引 还有可以,查多个索引
CountRequest countRequest1 = new CountRequest(“student-2021-12-22*”);

if(!elasticsearchTemplate.indexExists(student.getClass())){
System.out.println("create index at "+DateUtil.now());
elasticsearchTemplate.createIndex(student.getClass());
elasticsearchTemplate.putMapping(student.getClass());
}

创建模板
PUT _template/template_1
{
“template”: “test-*”,
“settings”: {
“number_of_shards”: 1
},
“mappings”: {
“type1”: {
“_source”: {
“enabled”: false
},
“properties”: {
“host_name”: {
“type”: “keyword”
},
“created_at”: {
“type”: “date”,
“format”: “EEE MMM dd HH:mm:ss Z YYYY”
}
}
}
}
}

es还有个作用就是分库分表!!!!!! test-身份证余数-时间!!!! 查询可拼接索引名称快速定位到
通过动态来分配数据到指定的表中 通过计算身份证后2位的余数分配到不同的表中!!!

es优化 节点N*(1.5-3)
一个lucene一个分片也只能最多存储20亿个文档。 另外,我们也建议一个分片的大小在20G - 40G,最大不能超过 50G 太大的话查询时会比较慢
1.时间动态建立存在某段时间数据量集中,导致索引分片超过设计容量的问题
2.Rollover 的原理是使用一个别名指向真正的索引,当指向的索引满足一定条件(文档数或时间或索引大小)更新实际指向的索引 必须明确执行了rollover指令 对于开发者来说不够自动化
3.使用 ILM(Index Lifecycle Management ) 管理索引 索引从生到死的过程, Hot(热数据 写读) -> Warm(不可写多查) -> Cold(冷数据 读) -> Delete

更好的硬盘,CPU io提升 SSD固态硬盘,靠的是电路的扫描和开关作用将信息读出和写入,不存在机械动作!!!
Coordinating节点:协调节点用于做分布式里的协调,将各分片或节点返回的数据整合后返回。 可以通过设置node.master、node.data 、 node.ingest 都为 false 来设置专门的协调节点。需要较好的CPU和较高的内存。

我们很有必要将一半的物理内存留给lucene ; 另一半的物理内存留给ES(JVM heap )
设置refresh_interval 为-1,同时设置number_of_replicas 为0,通过关闭refresh间隔周期,同时不设置副本来提高写性能。写节点关闭
translog时间和大小 减少Io
用index filed属性,analyzed 和not_analyzed,根据业务需求来控制字段是否分词或不分词
禁止深分页查询 字段个数 批量bulk:写入不易太大,否则会频繁触发gc操作,导致写入线程阻塞。

设置参数,禁止OS将es进程swap出去 您应该确保操作系统不会swapping out the java进程 通过使用自动生成的ID,Elasticsearch可以跳过这个检查,这使索引更快。
不要 返回大的结果集 搜索请求通过round-robin轮询机制选中主分片和副本分片

es7去掉了类型
get post 就是参数带在哪里
put 更新或创建数据(指定id) post创建文档是随机的id
_search  查数据
_mapping 索引结构

curl -X GET "localhost:9200/_cat/indices?v"

{
	"query": {
		"bool": {
			"must": [
				{
					"range": {
						"happen_time": {
							"from": "2021-11-29 00:00:00",
							"to": "2021-11-30 00:00:00"
						}
					}
				}
			]
		}
	},
	"size": 0,
	"aggs": {
		"sips": {
			"terms": {
				"field": "s_ip.keyword"
			}
		}
	}
}


{
	"size": 0,
	"query": {
		"bool": {
			"must": [
				{
					"range": {
						"happen_time": {
							"from": 1,
							"to": 200000000000
						}
					}
				},
				{
					"terms": {
						"k.keyword": [
							"sss",
							""
						]
					}
				}
			]
		}
	},
	"aggs": {
		"markeds": {
			"terms": {
				"field": "marked_type.keyword",
				"size": 100,
				"sourt": ">max_time"
			},
			"aggs": {
				"ips": {
					"terms": {
						"filed": "d_ip"
					}
				}
			}
		}
	}
}



{
	"size": 0,
	"query": {
		"bool": {}
	},
	"aggs": {
		"markeds": {
			"range": {
				"field": "happen_time",
				"ranges": [
					{
						"key": "time1",
						"from": "2021-12-06 00:40:58",
						"to": "2021-12-06 23:40:58"
					},
					{
						"key": "time2",
						"from": "2021-12-07 00:40:58",
						"to": "2021-12-07 23:40:58"
					}
				]
			},
			"aggs": {
				"grads": {
					"terms": {
						"field": "marked_type.keyword"
					}
				}
			}
		}
	}
}
```aggregation和query同级  结果也是统计的

RangeAggregationBuilder rangeAgg = AggregationBuilders.range("times").field("happen_time");
for (QueryTimeVo range : ranges) {
	//es 这里range时间戳需要加8小时
	rangeAgg.addRange(range.getKey(),range.getStartTime()+8 * 60 * 60 * 1000,range.getEndTime()+8 * 60 * 60 * 1000);
}
rangeAgg.subAggregation(AggregationBuilders.terms("hi").field("grade.keyword"));  //先按时间分级 再按字段group by


指定字段
String[] fields = {"src_ip","dest_ip"};
sourceBuilder.fetchSource(fields,null);

		
SearchRequest searchRequest = new SearchRequest("connect");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.rangeQuery("time")
		.from(startTime)
		.to(endTime));

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
sourceBuilder.query(boolQueryBuilder);
String script;
if(ipType==1){
	script="doc['d_ip'].value + ' ' + doc['trans_pro.keyword'].value+' '+ doc['d_port'].value+ ' ' + doc['app_pro.keyword'].value";
}else{
	script="doc['s_ip'].value + ' ' + doc['trans_pro.keyword'].value+' '+ doc['d_port'].value+ ' ' + doc['app_pro.keyword'].value";
}
//制定字段进行重复数据输出
TermsAggregationBuilder repeats = AggregationBuilders.terms("repeats").script(new Script(script));

//这里是指  重复的数据条数  需求上设置1000数据库获取
repeats.minDocCount(repeatData);
repeats.size(1000);

TermsAggregationBuilder ipTermsBuilder;
if(ipType==1){
	ipTermsBuilder = AggregationBuilders.terms("ips").field("s_ip");
}else{
	ipTermsBuilder = AggregationBuilders.terms("ips").field("d_ip");
}
repeats.subAggregation(ipTermsBuilder);
ipTermsBuilder.subAggregation(AggregationBuilders.min("min_time").field("time"));
ipTermsBuilder.subAggregation(AggregationBuilders.max("max_time").field("time"));

sourceBuilder.aggregation(repeats);
searchRequest.source(sourceBuilder);
//System.out.println(sourceBuilder);
SearchResponse searchResponse = null;
try {
	searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
	e.printStackTrace();
}
return searchResponse;



ParsedStringTerms protocol = searchResponse.getAggregations().get("repeats");
for(Terms.Bucket bucket : protocol.getBuckets()){
 String ipStr = sipBucket.getKeyAsString();
 long docCount = sipBucket.getDocCount();


获取结果Bool
SearchHit[] hits = searchResponse.getHits().getHits();
Set<String> set = new HashSet<>();
for (SearchHit hit : hits) {
	Map<String, Object> map = hit.getSourceAsMap();
	String sIp = map.get("src_ip").toString();
	
	 LocalDateTime startTime = timeParam.getStartTime();
        LocalDateTime endTime = timeParam.getEndTime();
        SearchRequest searchRequest = new SearchRequest("base_anomaly_device");

        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (areaIdList != null) {
            QueryBuilder queryBuilder = QueryBuilders.termsQuery("area_id", areaIdList);
            boolQueryBuilder.must(queryBuilder);
        }
        if (unitIdList != null) {
            QueryBuilder queryBuilder = QueryBuilders.termsQuery("unit_id", unitIdList);
            boolQueryBuilder.must(queryBuilder);
        }

        boolQueryBuilder.must(QueryBuilders.rangeQuery("happen_time")
                .lte(df.format(endTime))
                .gte(df.format(startTime)));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.size(0);
        searchSourceBuilder.query(boolQueryBuilder);

        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("device_type").field("device_type.keyword");
        searchSourceBuilder.aggregation(termsAggregationBuilder);

        searchRequest.source(searchSourceBuilder);

        Map<String, Object> resultMap = new HashMap<>();
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            ParsedStringTerms typeAgg = searchResponse.getAggregations().get("device_type");
            if(typeAgg.getBuckets().size()>0){
                for(Terms.Bucket bucket : typeAgg.getBuckets()){
                    resultMap.put("all"+bucket.getKeyAsString(),bucket.getDocCount());
                }
            }
			
			ParsedStringTerms typeAgg = searchResponse.getAggregations().get("device_type");
            if(typeAgg.getBuckets().size()>0){
                for(Terms.Bucket bucket : typeAgg.getBuckets()){
                    ParsedStringTerms ipAgg=bucket.getAggregations().get("ip");
                    resultMap.put("all"+bucket.getKeyAsString(),ipAgg.getBuckets().size());
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return resultMap;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值