如果没有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"
    }
  }
}

返回信息包含

  1. 查询阶段(Query Phase)

    • query:查询执行详情
    • rewrite_time:查询重写时间
    • collectors:结果收集器信息
  2. 获取阶段(Fetch Phase)

    • fetch:文档获取详情
    • load_source:源数据加载时间
  3. 聚合阶段(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

🎯 关键结论

  1. 所有三个条件都匹配成功

    • prize_type=8 ✅
    • reward_time 字段存在 ✅
    • es_delete_flag="F" ✅
  2. 但最终评分是0

    • 这是因为您使用的是 filter 上下文(不是 query 上下文)
    • 在过滤上下文中,Elasticsearch 不计算相关性评分,所有匹配文档的评分都是0
    • 这是正常且预期的行为!
  3. # 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个分片上的详细性能分析。让我为您详细解读:

🔍 整体查询结构

您的查询包含三个必须条件:

  1. prize_type:[8 TO 8] - prize_type等于8
  2. ConstantScore(DocValuesFieldExistsQuery [field=reward_time]) - reward_time字段存在
  3. 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_doc
  • reward_time字段存在检查:性能较差,advance操作耗时严重
  • es_delete_flag:F:性能中等,advance操作耗时较多

💡 问题识别

🔴 主要性能问题
  1. DocValuesFieldExistsQuery 性能瓶颈

    • 检查 reward_time 字段是否存在消耗了大量时间
    • 每个分片需要 advance 操作约2.4万次
  2. es_delete_flag 查询优化空间

    • Term查询的advance操作也有优化空间
🟢 良好表现
  • prize_type 范围查询性能良好
  • 三个分片性能相对均衡(3.8-4.1毫秒)
  • 查询重写时间很短(10-25微秒)

🚀 最佳实践

  1. Explain 使用时机

    • 当搜索结果不符合预期时
    • 需要理解评分模型时
    • 调试 boosting 和权重设置
  2. Profile 使用时机

    • 查询响应时间过长时
    • 需要优化复杂聚合时
    • 识别索引或映射问题
  3. 生产环境注意

    • 两者都会增加查询开销,避免在生产环境频繁使用
    • 建议在开发或测试环境进行调试

问题!!!


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可以使用两个线程异步一起查询。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐