elasticsearch-query-optimization
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseElasticsearch Query DSL Optimization
Elasticsearch Query DSL 优化
Diagnose why a Query DSL search is slow, identify the dominant cost from the profile (not guesswork), rewrite the query
to remove that cost while preserving match semantics, and re-measure with profiling enabled.
<!-- begin-partial: preamble -->诊断Query DSL搜索缓慢的原因,通过分析结果(而非猜测)确定主要开销来源,重写查询以消除该开销同时保留匹配语义,并在启用分析的情况下重新衡量性能。
<!-- begin-partial: preamble -->Environment Configuration
环境配置
This skill executes Elasticsearch operations through the CLI. If the
CLI is not installed, tell the user what it is needed for. Do
not guess credentials, call the HTTP API directly, or attempt other workarounds.
elasticelasticThis skill references operations in HTTP-shorthand form (e.g., , , ,
, ). The Operations table at the end of this document
maps each shorthand to the equivalent CLI command — always use the CLI rather than calling the HTTP API
directly.
<!-- end-partial: preamble -->
GET /GET /_cat/indicesGET /{index}/_mappingGET /{index}/_settings/index.modePOST /_queryelasticScope: Query DSL searches via. This skill does not migrate queries to ES|QL — it optimizes the existing bool/match/term/wildcard structure the user already runs.POST /{index}/_searchGround rule: Never recommend "add shards" or "scale hardware" as the primary fix when the profile names a specific clause (for exampleat ~3.8s). Fix the query first; infrastructure changes require evidence the query is already optimal.WildcardQuery
此技能通过 CLI执行Elasticsearch操作。如果未安装 CLI,请告知用户其必要性。请勿猜测凭据、直接调用HTTP API或尝试其他变通方法。
elasticelastic此技能以HTTP简写形式引用操作(例如、、、、)。本文档末尾的操作表格将每个简写映射为等效的 CLI命令——请始终使用CLI而非直接调用HTTP API。
<!-- end-partial: preamble -->
GET /GET /_cat/indicesGET /{index}/_mappingGET /{index}/_settings/index.modePOST /_queryelastic范围: 通过执行的Query DSL搜索。此技能不会将查询迁移至ES|QL——它仅优化用户当前运行的现有bool/match/term/wildcard结构。POST /{index}/_search基本原则: 当分析结果明确指出具体子句(例如耗时约3.8秒的)时,切勿将“添加分片”或“升级硬件”作为主要修复方案。优先修复查询;只有在证明查询已达最优状态后,才考虑基础设施变更。WildcardQuery
Process
流程
-
Confirm connectivity and locate the target index. Call. If the call fails, stop — do not guess endpoints or credentials. When the user names an index pattern (for example
GET /), narrow candidates withlogs-*and pick the index or pattern the query actually targets.GET /_cat/indicesDecision: proceed only when the index is known. Data needed: index name or pattern, and the slow Query DSL body (from the user or from a saved search). -
Profile the slow query to find the dominant cost. Callwith
POST /{index}/_searchand the user's query unchanged. Read"profile": true, then inspecttook— sort child collectors byprofile.shards[].searches[].queryand identify the top contributor.time_in_nanosDecision: classify the bottleneck from profile evidence:- /
TermQuery/PointRangeQueryinsideMatchNoDocsQueryalongside a scoring clause — exact-match or range filters are being scored unnecessarily. Likely fix: move them tomustcontext (step 4a).filter - with a leading
WildcardQuery(for example*) — cannot use the inverted index; scans terms per document. Likely fix: remove the leading wildcard (step 4b).message:*timeout* - on a
MatchQueryfield — expected scoring cost; optimize only if profile shows it dominates after filter-context fixes.text - High time — separate from query tuning; profile the agg tree (out of scope unless the user asked about aggs).
aggregation
Data needed: profile tree with,type,description, andtime_in_nanos(especiallybreakdownfor wildcards). Quote the top contributor verbatim when explaining the diagnosis.next_doc -
Inspect field mappings before rewriting. Call. For every clause you will move or rewrite, confirm the field type:
GET /{index}/_mapping- /
term/termson exact values — field must befilter(or another non-analyzed type). Akeywordon atermfield is a common bug; if types are wrong, say so and suggest the correct sub-field (for exampletext) or a mapping change — do not silently rewrite.service.keyword - /
match— target amatch_phrasefield (analyzed).text - — works on
wildcardorkeywordtypes; leadingwildcardstill forces a scan regardless of type.*
Decision: only propose rewrites that match confirmed types. Data needed: mapping for each field referenced in the query. -
Rewrite the query to remove the profiled bottleneck.
4a. Move non-scoring clauses from
tomustfilterWhen exact-match/term/terms/rangeon a keyword (or other non-scoring intent) clauses sit inmatchalongside a full-textmustthat should drive relevance:match- Move exact-match clauses into (or a
bool.filterarray entry).filter - Keep only clauses that must affect in
_score(typically the full-textbool.must).match
Why: filter context skips scoring and participates in the filter/bitset cache on repeated queries. Semantics: the same documents match; only scoring and performance change — state this explicitly.Example rewrite pattern:json{ "query": { "bool": { "filter": [{ "term": { "status": "active" } }, { "term": { "tenant_id": "acme" } }], "must": [{ "match": { "description": "wireless keyboard" } }] } } }4b. Eliminate leading wildcards
When the profile showswithWildcardQuerylikedescriptionand highmessage:*timeout*time, the leadingnext_docprevents index lookup. Choose a fix based on mapping and user intent (substring vs prefix vs exact):*Intent Preferred rewrite Full-text substring in logs ormatchon the analyzedmatch_phrasemessagefieldtextLiteral substring on keyword -typed field, or reindex with ngram analyzerwildcardPrefix only ( )timeout*query onprefix, or edge ngram at index timekeywordAlso move any non-scoring exact match (for exampleon a keyword) into{ "match": { "service": "checkout" } }— usefilteron the keyword field when the mapping confirms it.termExample rewrite pattern:json{ "query": { "bool": { "filter": [{ "term": { "service.keyword": "checkout" } }], "must": [{ "match": { "message": "timeout" } }] } } }Adjust field names (vsservice) to match the mapping from step 3.service.keyword4c. Optional — validate rewrite before profiling
When semantics are uncertain (for example changingtowildcardmay include analyzed tokens the wildcard excluded), callmatchwith the rewritten query and read the explanation for obvious mismatches.POST /{index}/_validate/query?explain=trueDecision: pick the smallest rewrite that addresses the profiled cost. Data needed: rewritten Query DSL body. - Move exact-match clauses into
-
Re-profile the rewritten query and compare. Callagain with
POST /{index}/_searchand the rewritten query. Compare"profile": trueand the top profile collector to the baseline from step 2.tookDecision: report success only when the dominant collector changed ordropped materially. If the profile still shows a leading wildcard or scored filters, iterate — do not declare victory fromtime_in_nanosalone without profile confirmation.tookData needed: before/after profile summaries (top collector,type,description).time_in_nanos -
Report findings in this order.
- Root cause — quote the profile (for example "
WildcardQuery≈ 3.8s, mostlymessage:*timeout*").next_doc - Rewrite — show the optimized bool structure with filter vs must separation.
- Mapping notes — keyword vs text confirmations from .
GET /{index}/_mapping - Measured improvement — before/after profile or from step 5.
took - Semantic caveat — only if the rewrite could change which documents match (for example vs substring
match).wildcard
- Root cause — quote the profile (for example "
-
确认连接性并定位目标索引。调用。如果调用失败,请停止操作——请勿猜测端点或凭据。当用户指定索引模式(例如
GET /)时,使用logs-*缩小候选范围,并选择查询实际指向的索引或模式。GET /_cat/indices决策: 仅在确定索引后继续。所需数据: 索引名称或模式,以及缓慢的Query DSL查询体(来自用户或已保存的搜索)。 -
分析缓慢查询以找到主要开销。调用,添加
POST /{index}/_search参数并保持用户查询不变。读取"profile": true值,然后检查took——按profile.shards[].searches[].query对子收集器排序,确定主要贡献者。time_in_nanos决策: 根据分析证据对瓶颈进行分类:- 中包含
must/TermQuery/PointRangeQuery以及评分子句——精确匹配或范围过滤器被不必要地评分。可能的修复:将它们移至MatchNoDocsQuery上下文(步骤4a)。filter - 带有前导的
*(例如WildcardQuery)——无法使用倒排索引;需逐个文档扫描词条。可能的修复:移除前导通配符(步骤4b)。message:*timeout* - 字段上的
text——预期的评分开销;仅当分析结果显示在修复过滤器上下文后该开销仍占主导时才进行优化。MatchQuery - 高耗时——与查询调优分离;需分析聚合树(除非用户询问聚合,否则不在本技能范围内)。
aggregation
所需数据: 包含、type、description和time_in_nanos(尤其是通配符的breakdown)的分析树。解释诊断时请逐字引用主要贡献者。next_doc -
重写前检查字段映射。调用。对于每个将要移动或重写的子句,确认字段类型:
GET /{index}/_mapping- 精确值上的/
term/terms——字段必须为filter(或其他非分析类型)。keyword字段上使用text是常见错误;如果类型错误,请告知用户并建议正确的子字段(例如term)或映射变更——请勿静默重写。service.keyword - /
match——目标为match_phrase字段(已分析)。text - ——适用于
wildcard或keyword类型;无论类型如何,前导wildcard仍会强制扫描。*
决策: 仅提出与已确认类型匹配的重写方案。所需数据: 查询中引用的每个字段的映射。 - 精确值上的
-
重写查询以消除分析出的瓶颈。
4a. 将非评分子句从
移至mustfilter当精确匹配的/term/terms/range(针对keyword或其他非评分意图)子句与应驱动相关性的全文match一同位于match中时:must- 将精确匹配子句移至(或
bool.filter数组条目)。filter - 仅保留必须影响的子句在
_score中(通常为全文bool.must)。match
原因: 过滤器上下文会跳过评分,并且在重复查询时参与过滤器/位集缓存。语义: 匹配的文档保持不变;仅评分和性能发生变化——请明确说明这一点。重写示例模式:json{ "query": { "bool": { "filter": [{ "term": { "status": "active" } }, { "term": { "tenant_id": "acme" } }], "must": [{ "match": { "description": "wireless keyboard" } }] } } }4b. 消除前导通配符
当分析结果显示的描述类似于WildcardQuery且message:*timeout*耗时较高时,前导next_doc会阻止索引查找。根据映射和用户意图(子字符串、前缀或精确匹配)选择修复方案:*意图 首选重写方案 日志中的全文子字符串 在已分析的 message字段上使用text或matchmatch_phrase关键字上的字面子字符串 使用 类型字段,或使用ngram分析器重新索引wildcard仅前缀匹配( )timeout*在 上使用keyword查询,或在索引时使用edge ngram分析器prefix同时将任何非评分的精确匹配(例如针对keyword字段的)移至{ "match": { "service": "checkout" } }——当映射确认后,在keyword字段上使用filter。term重写示例模式:json{ "query": { "bool": { "filter": [{ "term": { "service.keyword": "checkout" } }], "must": [{ "match": { "message": "timeout" } }] } } }根据步骤3中的映射调整字段名称(vsservice)。service.keyword4c. 可选——分析前验证重写结果
当语义不确定时(例如将改为wildcard可能包含通配符排除的已分析词条),调用match并传入重写后的查询,读取解释以检查明显的不匹配。POST /{index}/_validate/query?explain=true决策: 选择最小的重写方案以解决分析出的开销。所需数据: 重写后的Query DSL查询体。 - 将精确匹配子句移至
-
重新分析重写后的查询并进行比较。再次调用,添加
POST /{index}/_search参数并使用重写后的查询。将"profile": true值和主要分析收集器与步骤2中的基准值进行比较。took决策: 仅当主要收集器发生变化或显著下降时,才报告优化成功。如果分析结果仍显示前导通配符或已评分过滤器,请迭代优化——请勿仅依据time_in_nanos值就宣告成功,必须有分析结果的确认。took所需数据: 优化前后的分析摘要(主要收集器的、type、description)。time_in_nanos -
按以下顺序报告结果。
- 根本原因——引用分析结果(例如“
WildcardQuery≈ 3.8秒,主要耗时在message:*timeout*”)。next_doc - 重写方案——展示优化后的bool结构,区分filter和must。
- 映射说明——来自的keyword与text类型确认。
GET /{index}/_mapping - 可衡量的改进——步骤5中的优化前后分析结果或值。
took - 语义注意事项——仅当重写可能改变匹配的文档集时(例如与子字符串
match的区别)才说明。wildcard
- 根本原因——引用分析结果(例如“
Guidelines
指南
- Profile first. If the user supplies a profile summary, use it — but still recommend re-profiling after changes.
- Filter is for equality, must is for relevance. Status, tenant ID, service name, and time ranges rarely belong in
when a text query drives ranking.
must - Leading wildcards are almost never the right fix for log search. Prefer analyzed /
match; reservematch_phrasefor suffix patterns (wildcard) on keyword ortimeout*-typed fields.wildcard - Do not conflate slow with wrong. A slow query can return correct results; optimization preserves the result set unless you explicitly warn about a semantic trade-off.
- Deep reference: profile collector types, filter-cache behavior, and wildcard alternatives — references/query-optimization-reference.md.
- 先分析。如果用户提供了分析摘要,请使用它——但仍建议在变更后重新分析。
- Filter用于相等匹配,Must用于相关性。状态、租户ID、服务名称和时间范围在文本查询驱动排名时,很少属于。
must - 前导通配符几乎永远不是日志搜索的正确解决方案。优先使用已分析的/
match;仅在keyword或match_phrase类型字段上保留wildcard用于后缀模式(wildcard)。timeout* - 请勿混淆缓慢与错误。缓慢的查询可能返回正确的结果;优化会保留结果集,除非您明确警告存在语义权衡。
- 深度参考: 分析收集器类型、过滤器缓存行为和通配符替代方案——references/query-optimization-reference.md。
Examples
示例
Unscored terms in must
mustmust
中的非评分term
mustInput: contains on , on , and on .
bool.musttermstatustermtenant_idmatchdescriptionDiagnosis: profile shows scored collectors alongside ; exact filters do not need scoring.
TermQueryMatchQueryFix: move both clauses to ; keep in . Confirm and are .
termfiltermatchmuststatustenant_idkeyword输入: 包含上的、上的以及上的。
bool.muststatustermtenant_idtermdescriptionmatch诊断: 分析结果显示收集器与一同被评分;精确过滤器无需评分。
TermQueryMatchQuery修复: 将两个子句移至;将保留在中。确认和为类型。
termfiltermatchmuststatustenant_idkeywordLeading wildcard dominates latency
前导通配符主导延迟
Input: plus on in . Profile: ~3.8s.
wildcardmessage:*timeout*matchservicemustWildcardQueryDiagnosis: leading forces term enumeration; not an index/shard problem.
*Fix: on analyzed ; move service to as on keyword. Re-profile — expect
to disappear or shrink to negligible time.
matchmessagefiltertermWildcardQuery输入: 中包含的以及上的。分析结果:耗时约3.8秒。
mustmessage:*timeout*wildcardservicematchWildcardQuery诊断: 前导强制枚举词条;并非索引/分片问题。
*修复: 在已分析的字段上使用;将service作为keyword上的移至。重新分析——预期会消失或耗时降至可忽略水平。
messagematchtermfilterWildcardQueryOperations
操作
| HTTP API (shorthand) | |
|---|---|
| |
| |
| |
| |
| |
Include in the search JSON body (or pass ) when profiling in steps 2 and 5.
"profile": true--profile true| HTTP API(简写) | |
|---|---|
| |
| |
| |
| |
| |
在步骤2和步骤5中分析时,请在搜索JSON体中包含(或传入参数)。
"profile": true--profile true