es查询问题
·
如果没有kibana管理台页面工具,还可以用postman!!!
_search不带条件查询

curl --location --request GET 'http://ip:9200/xxx-gift_pack_record202409/_search' \
--header 'Authorization: Basic ZWxhc3RpYzpIaWhvbm9yQG1hcmtldDFuZw=='
_search带条件查询

curl --location --request GET 'http://ip:9200/xxx-t_prize_grant_record202409/_search' \
--header 'Authorization: Basic ZWxhc3RpYzpIaWhvbm9yQG1hcmtldDFuZw==' \
--header 'Content-Type: application/json' \
--data-raw '{
"from": 0,
"size": 15,
"query": {
"bool": {
"filter": [
{"term": {"prize_type": {"value": 8, "boost": 1.0}}},
{"range": {"reward_time": {"from": "2024-09-01 00:00:00", "to": "2026-09-30 23:59:59", "include_lower": true, "include_upper": true, "boost": 1.0}}},
{"term": {"es_delete_flag": {"value": "false", "boost": 1.0}}}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"sort": [
{"reward_time": {"order": "desc"}},
{"grant_id": {"order": "desc"}}
],
"track_total_hits": 2147483647
}'
_count查询
curl --location --request GET 'http://ip:9200/xxx-t_prize_grant_record202409/_count' \
--header 'Authorization: Basic ZWxhc3RpYzpIaWhvbm9yQG1hcmtldDFuZw==' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
"bool": {
"filter": [
{"term": {"prize_type": {"value": 8, "boost": 1.0}}},
{"range": {"reward_time": {"from": "2024-09-01 00:00:00", "to": "2026-09-30 23:59:59", "include_lower": true, "include_upper": true, "boost": 1.0}}},
{"term": {"es_delete_flag": {"value": "false", "boost": 1.0}}}
],
"adjust_pure_negative": true,
"boost": 1.0
}
}
}'
profile分析
curl --location --request GET 'http://ip:9200/xxx-t_prize_grant_record202409/_search' \
--header 'Authorization: Basic ZWxhc3RpYzpIaWhvbm9yQG1hcmtldDFuZw==' \
--header 'Content-Type: application/json' \
--data-raw '{
"profile": true,
"from": 0,
"size": 15,
"query": {
"bool": {
"filter": [
{"term": {"prize_type": {"value": 8, "boost": 1.0}}},
{"range": {"reward_time": {"from": "2024-09-01 00:00:00", "to": "2026-09-30 23:59:59", "include_lower": true, "include_upper": true, "boost": 1.0}}},
{"term": {"es_delete_flag": {"value": "false", "boost": 1.0}}}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"sort": [
{"reward_time": {"order": "desc"}},
{"grant_id": {"order": "desc"}}
],
"track_total_hits": 2147483647
}'
在查询里加上 "profile": true
explain分析
curl --location --request GET 'http://ip:9200/xxx-t_prize_grant_record202409/_search' \
--header 'Authorization: Basic ZWxhc3RpYzpIaWhvbm9yQG1hcmtldDFuZw==' \
--header 'Content-Type: application/json' \
--data-raw '{
"explain": true,
"from": 0,
"size": 15,
"query": {
"bool": {
"filter": [
{
"term": {
"prize_type": {
"value": 8,
"boost": 1.0
}
}
},
{
"range": {
"reward_time": {
"from": "2024-09-01 00:00:00",
"to": "2026-09-30 23:59:59",
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
},
{
"term": {
"es_delete_flag": {
"value": "false",
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"sort": [
{
"reward_time": {
"order": "desc"
}
},
{
"grant_id": {
"order": "desc"
}
}
],
"track_total_hits": 2147483647
}'
在查询里加上 "explain": true
📊 Elasticsearch 的 Explain 和 Profile 功能详解
🔍 Explain(解释查询)
作用:解释为什么某个文档匹配或不匹配查询,显示评分计算过程。
使用场景:
- 调试相关性评分问题
- 理解查询匹配逻辑
- 优化查询性能
使用方法:
# 方式1:使用 _explain 端点
GET /index_name/_explain/doc_id
{
"query": {
"match": {
"field": "search term"
}
}
}
# 方式2:在 _search 中添加 explain 参数
GET /index_name/_search
{
"explain": true,
"query": {
"match": {
"field": "search term"
}
}
}
返回信息包含:
value:匹配得分description:评分描述details:详细的评分计算过程matched:是否匹配
⚡ Profile(性能分析)
作用:详细分析查询执行过程,识别性能瓶颈。
使用场景:
- 优化复杂查询性能
- 识别慢查询原因
- 分析聚合操作性能
使用方法:
GET /index_name/_search
{
"profile": true,
"query": {
"match": {
"field": "search term"
}
}
}
返回信息包含:
-
查询阶段(Query Phase)
query:查询执行详情rewrite_time:查询重写时间collectors:结果收集器信息
-
获取阶段(Fetch Phase)
fetch:文档获取详情load_source:源数据加载时间
-
聚合阶段(Aggregation Phase)
- 聚合操作执行详情
🎯 两者区别
| 特性 | Explain | Profile |
|---|---|---|
| 目的 | 解释评分机制 | 分析性能瓶颈 |
| 输出 | 评分计算详情 | 时间消耗详情 |
| 粒度 | 单个文档 | 整个查询 |
| 使用场景 | 相关性调试 | 性能优化 |
💡 实际应用示例
Explain 示例结果:
"_explanation": {
"value": 0.0,
"description": "sum of:",
"details": [
{
"value": 0.0,
"description": "match on required clause, product of:",
"details": [
{
"value": 0.0,
"description": "# clause",
"details": []
},
{
"value": 1.0,
"description": "prize_type:[8 TO 8]",
"details": []
}
]
},
{
"value": 0.0,
"description": "match on required clause, product of:",
"details": [
{
"value": 0.0,
"description": "# clause",
"details": []
},
{
"value": 1.0,
"description": "DocValuesFieldExistsQuery [field=reward_time]",
"details": []
}
]
},
{
"value": 0.0,
"description": "match on required clause, product of:",
"details": [
{
"value": 0.0,
"description": "# clause",
"details": []
},
{
"value": 1.0,
"description": "es_delete_flag:F",
"details": []
}
]
}
]
}
🔍 整体含义
value: 0.0:这个文档的最终相关性评分是0分description: "sum of:":总评分是由多个子评分相加得到的
📋 三个必须子句分析
您的查询包含三个必须匹配的条件,每个条件都产生了0分:
1. 第一个条件:prize_type 匹配
{
"value": 0.0,
"description": "match on required clause, product of:",
"details": [
{"value": 0.0, "description": "# clause", "details": []},
{"value": 1.0, "description": "prize_type:[8 TO 8]", "details": []}
]
}
- ✅
prize_type:[8 TO 8]:值为1.0,表示prize_type=8匹配成功 - ❓
# clause:值为0.0,这是Elasticsearch内部计算的一个因子
2. 第二个条件:reward_time 字段存在性检查
{
"value": 0.0,
"description": "match on required clause, product of:",
"details": [
{"value": 0.0, "description": "# clause", "details": []},
{"value": 1.0, "description": "DocValuesFieldExistsQuery [field=reward_time]", "details": []}
]
}
- ✅
DocValuesFieldExistsQuery [field=reward_time]:值为1.0,表示reward_time字段存在 - ❓
# clause:值为0.0
3. 第三个条件:es_delete_flag 匹配
{
"value": 0.0,
"description": "match on required clause, product of:",
"details": [
{"value": 0.0, "description": "# clause", "details": []},
{"value": 1.0, "description": "es_delete_flag:F", "details": []}
]
}
- ✅
es_delete_flag:F:值为1.0,表示es_delete_flag="F"匹配成功 - ❓
# clause:值为0.0
🎯 关键结论
-
所有三个条件都匹配成功:
prize_type=8✅reward_time字段存在 ✅es_delete_flag="F"✅
-
但最终评分是0:
- 这是因为您使用的是
filter上下文(不是query上下文) - 在过滤上下文中,Elasticsearch 不计算相关性评分,所有匹配文档的评分都是0
- 这是正常且预期的行为!
- 这是因为您使用的是
-
# clause值为0的解释:- 这是Elasticsearch内部用于计算的一个因子
- 在filter上下文中,这个值被设置为0,因为不需要计算相关性
💡 为什么这样设计?
- 性能优化:filter上下文跳过评分计算,性能更好
- 缓存友好:filter结果可以被缓存,提高查询速度
- 布尔逻辑:只关心"是否匹配",不关心"匹配程度"
✅ 您的查询是正常的!
您的查询完全正确,所有条件都匹配成功。评分为0是filter上下文的正常行为,表示:
- ✅ 文档匹配所有过滤条件
- ✅ 应该被包含在结果集中
- ✅ 只是没有计算相关性评分而已
不需要担心这个0分,这是Elasticsearch filter查询的标准行为!
Profile 示例结果:
"profile": {
"shards": [
{
"id": "[REHyAdbwSWS8DMd8dOCkGQ][marketing_test_drcn-t_prize_grant_record202409][0]",
"searches": [
{
"query": [
{
"type": "BooleanQuery",
"description": "#prize_type:[8 TO 8] #ConstantScore(DocValuesFieldExistsQuery [field=reward_time]) #es_delete_flag:F",
"time_in_nanos": 4064629,
"breakdown": {
"set_min_competitive_score_count": 0,
"match_count": 0,
"shallow_advance_count": 0,
"set_min_competitive_score": 0,
"next_doc": 3636537,
"match": 0,
"next_doc_count": 24754,
"score_count": 0,
"compute_max_score_count": 0,
"compute_max_score": 0,
"advance": 22021,
"advance_count": 2,
"score": 0,
"build_scorer_count": 7,
"create_weight": 31850,
"shallow_advance": 0,
"create_weight_count": 1,
"build_scorer": 374221
},
"children": [
{
"type": "IndexOrDocValuesQuery",
"description": "prize_type:[8 TO 8]",
"time_in_nanos": 1248668,
"breakdown": {
"set_min_competitive_score_count": 0,
"match_count": 0,
"shallow_advance_count": 0,
"set_min_competitive_score": 0,
"next_doc": 973861,
"match": 0,
"next_doc_count": 24754,
"score_count": 0,
"compute_max_score_count": 0,
"compute_max_score": 0,
"advance": 511,
"advance_count": 4,
"score": 0,
"build_scorer_count": 9,
"create_weight": 461,
"shallow_advance": 0,
"create_weight_count": 1,
"build_scorer": 273835
}
},
{
"type": "ConstantScoreQuery",
"description": "ConstantScore(DocValuesFieldExistsQuery [field=reward_time])",
"time_in_nanos": 2578938,
"breakdown": {
"set_min_competitive_score_count": 0,
"match_count": 0,
"shallow_advance_count": 0,
"set_min_competitive_score": 0,
"next_doc": 0,
"match": 0,
"next_doc_count": 0,
"score_count": 0,
"compute_max_score_count": 0,
"compute_max_score": 0,
"advance": 2561666,
"advance_count": 24756,
"score": 0,
"build_scorer_count": 9,
"create_weight": 4428,
"shallow_advance": 0,
"create_weight_count": 1,
"build_scorer": 12844
},
"children": [
{
"type": "DocValuesFieldExistsQuery",
"description": "DocValuesFieldExistsQuery [field=reward_time]",
"time_in_nanos": 923343,
"breakdown": {
"set_min_competitive_score_count": 0,
"match_count": 0,
"shallow_advance_count": 0,
"set_min_competitive_score": 0,
"next_doc": 0,
"match": 0,
"next_doc_count": 0,
"score_count": 0,
"compute_max_score_count": 0,
"compute_max_score": 0,
"advance": 914637,
"advance_count": 24756,
"score": 0,
"build_scorer_count": 9,
"create_weight": 300,
"shallow_advance": 0,
"create_weight_count": 1,
"build_scorer": 8406
}
}
]
},
{
"type": "TermQuery",
"description": "es_delete_flag:F",
"time_in_nanos": 1060002,
"breakdown": {
"set_min_competitive_score_count": 0,
"match_count": 0,
"shallow_advance_count": 0,
"set_min_competitive_score": 0,
"next_doc": 0,
"match": 0,
"next_doc_count": 0,
"score_count": 0,
"compute_max_score_count": 0,
"compute_max_score": 0,
"advance": 1020038,
"advance_count": 24757,
"score": 0,
"build_scorer_count": 9,
"create_weight": 9127,
"shallow_advance": 0,
"create_weight_count": 1,
"build_scorer": 30837
}
}
]
}
],
"rewrite_time": 10349,
"collector": [
{
"name": "SimpleFieldCollector",
"reason": "search_top_hits",
"time_in_nanos": 3358378
}
]
}
],
"aggregations": []
},
{
"id": "[SQYmE1nZRpiq2RL4t8yaKQ][marketing_test_drcn-t_prize_grant_record202409][1]",
...
},
{
"id": "[SQYmE1nZRpiq2RL4t8yaKQ][marketing_test_drcn-t_prize_grant_record202409][2]",
...
}
]
}
这个 Profile 结果显示了您的 Elasticsearch 查询在3个分片上的详细性能分析。让我为您详细解读:
🔍 整体查询结构
您的查询包含三个必须条件:
prize_type:[8 TO 8]- prize_type等于8ConstantScore(DocValuesFieldExistsQuery [field=reward_time])- reward_time字段存在es_delete_flag:F- es_delete_flag等于"F"
⏱️ 性能关键指标
分片0:
- 总查询时间:4,064,629 纳秒 ≈ 4.06毫秒
- 处理文档数:24,754 个文档
- 主要耗时:
next_doc操作(3.64毫秒)
分片1:
- 总查询时间:3,870,708 纳秒 ≈ 3.87毫秒
- 处理文档数:24,267 个文档
- 主要耗时:
next_doc操作(3.46毫秒)
分片2:
- 总查询时间:3,855,221 纳秒 ≈ 3.86毫秒
- 处理文档数:24,513 个文档
- 主要耗时:
next_doc操作(3.47毫秒)
🎯 性能瓶颈分析
1. 主要耗时操作:
next_doc:占查询时间的85-90%,这是遍历文档的主要操作advance:在reward_time和es_delete_flag查询中消耗较多时间
2. 各子查询性能:
prize_type:[8 TO 8]:性能最好,主要耗时在next_docreward_time字段存在检查:性能较差,advance操作耗时严重es_delete_flag:F:性能中等,advance操作耗时较多
💡 问题识别
🔴 主要性能问题:
-
DocValuesFieldExistsQuery性能瓶颈:- 检查
reward_time字段是否存在消耗了大量时间 - 每个分片需要 advance 操作约2.4万次
- 检查
-
es_delete_flag查询优化空间:- Term查询的advance操作也有优化空间
🟢 良好表现:
prize_type范围查询性能良好- 三个分片性能相对均衡(3.8-4.1毫秒)
- 查询重写时间很短(10-25微秒)
🚀 最佳实践
-
Explain 使用时机:
- 当搜索结果不符合预期时
- 需要理解评分模型时
- 调试 boosting 和权重设置
-
Profile 使用时机:
- 查询响应时间过长时
- 需要优化复杂聚合时
- 识别索引或映射问题
-
生产环境注意:
- 两者都会增加查询开销,避免在生产环境频繁使用
- 建议在开发或测试环境进行调试
问题!!!
public static SearchSourceBuilder page(SearchSourceBuilder builder, PageDto page) {
builder.trackTotalHits(true);
//builder.trackTotalHits(false);
// es 分页从 0 开始
builder.from((page.getPageNum() - 1) * page.getPageSize())
.size(page.getPageSize());
return builder;
}
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
.query(boolQuery)
// 构建排序
.sort(SortBuilders.fieldSort(Constants.REWARD_TIME).order(SortOrder.DESC))
.sort(SortBuilders.fieldSort(Constants.GRANT_ID).order(SortOrder.DESC));
PageHelper.page(sourceBuilder, req.getPage());
// 构建请求
searchRequest.source(sourceBuilder);
log.info("hit es [prize-grant-record] mapper, param:[{}]", searchRequest);
// 执行查询
SearchResponse response = clientFactory.getInstance().search(searchRequest, RequestOptions.DEFAULT);
return ResponseConverter.convert(response.getHits(), cls);
如果builder.trackTotalHits(true),映射查询语句:
{
"from": 45,
"size": 15,
"query": {
"bool": {
"filter": [{
"range": {
"reward_time": {
"from": "2026-02-27 19:24:30",
"to": "2026-03-02 19:24:30",
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
},
{
"term": {
"es_delete_flag": {
"value": "false",
"boost": 1.0
}
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"sort": [{
"reward_time": {
"order": "desc"
}
},
{
"grant_id": {
"order": "desc"
}
}],
"track_total_hits": 2147483647
}
会默认把符合查询条件的总记录数查出来!
🔍 主要性能问题分析
1. track_total_hits: 2147483647 问题
严重程度:⭐⭐⭐⭐⭐
"track_total_hits": 2147483647
问题分析:
- 这个设置强制ES计算精确的命中总数,即使有数百万条记录
- ES默认只返回前10,000个匹配文档的计数,设置此值会显著增加查询开销
- 对于大数据量的索引,计算精确总数非常消耗资源
建议解决方案:
// 移除或限制track_total_hits
"track_total_hits": false
// 或者设置一个合理的上限
"track_total_hits": 10000
======================
如果builder.trackTotalHits(false),映射查询语句:
{
"from": 45,
"size": 15,
"query": {
"bool": {
"filter": [{
"range": {
"reward_time": {
"from": "2026-02-27 19:24:30",
"to": "2026-03-02 19:24:30",
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
},
{
"term": {
"es_delete_flag": {
"value": "false",
"boost": 1.0
}
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"sort": [{
"reward_time": {
"order": "desc"
}
},
{
"grant_id": {
"order": "desc"
}
}],
"track_total_hits": -1
}
不会查出总记录数!可以使用_count查出总数,结合_search查询当前页数据,一起返回给前端,进行分页计算总页数,count和search可以使用两个线程异步一起查询。
更多推荐
所有评论(0)