用PROFILE API 定位 ES 慢查询

本文探讨了Elasticsearch 2.2版本引入的Profile API,该API允许用户检查查询执行时间及详细信息。通过创建单分片索引并进行查询,展示了Profile API如何揭示查询的内部工作,包括查询类型、Lucene方法、执行时间、重写时间和收集器的使用,帮助优化查询性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载处:https://www.easyice.cn/archives/267

有时在发起一个查询时,他会被延迟,或者响应时间很慢,查询缓慢可能会有多种原因;范围包括 shard 问题,或者计算查询中的某些元素。 从 elasticsearch 2.2版本开始提供 Profile API 供用户检查查询执行时间和其他详细信息。在这篇博客中,我们将探讨如何使用profile API查看查询计时。

Profile API


Profile API 是Elasticsearch 2.2版本的一个实验性特性, Profile API 返回所有分片的详细信息。为了简单起见,我们创建一个只有1个分片的索引。

Index creation:

 

 

1

2

3

4

5

6

7

8

 

curl -XPUT http:localhost:9200/myindex -d '{

"settings":{

    "number_of_replicas": 0,

    "number_of_shards": 1

}

}'

 

 

在上面创建的索引中,我们为演示基本的搜索写入若干文档,然后从结果中解释 profile API。让我们索引三个doc:

 

 

1

2

3

4

5

6

7

8

9

10

11

 

curl -XPOST http://localhost:9200/myindex/mytype/1 -d '{

"brand" : "Cotton Plus"

}'

curl -XPOST http://localhost:9200/myindex/mytype/2 -d '{

"brand" : "Van Huesen"

}'

curl -XPOST http://localhost:9200/myindex/mytype/3 -d '{

"brand" : "Arrow"

}'

 

 

可以通过在 query 部分上方提供 “profile: true” 来启用Profile API。让我们来看看带profile参数的 query 在单个查询中长什么样子:

 

 

1

2

3

4

5

6

7

8

9

10

 

curl XPOST http://localhost:9200/myindex/mytype/_search -d '{

"profile": true,

     "query": {

       "match": {

         "brand": "Cotton Plus"

       }

     }

}'

 

 

Profile API的结果是基于每个分片计算的。由于在我们的例子中只有一个分片,我们在profile API响应的分片数组中只有一个数组元素,如下所示:

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

 

{

"shards": [

   {

     "id": "[egPYczsCRTqaeJ8jKhFjtw][myindex][0]",

     "searches": [

       {

         "query": [

           {

             "query_type": "BooleanQuery",

             "lucene": "brand:levi brand:goals",

             "time": "1.293761000ms",

             "breakdown": {

               "score": 0,

               "create_weight": 136078,

               "next_doc": 0,

               "match": 0,

               "build_scorer": 1082113,

               "advance": 0

             },

             "children": [

               {

                 "query_type": "TermQuery",

                 "lucene": "brand:levi",

                 "time": "0.04626300000ms",

                 "breakdown": {

                   "score": 0,

                   "create_weight": 30190,

                   "next_doc": 0,

                   "match": 0,

                   "build_scorer": 16073,

                   "advance": 0

                 }

               },

               {

                 "query_type": "TermQuery",

                 "lucene": "brand:goals",

                 "time": "0.02930700000ms",

                 "breakdown": {

                   "score": 0,

                   "create_weight": 16600,

                   "next_doc": 0,

                   "match": 0,

                   "build_scorer": 12707,

                   "advance": 0

                 }

               }

             ]

           }

         ],

         "rewrite_time": 64032,

         "collector": [

           {

             "name": "TotalHitCountCollector",

             "reason": "search_count",

             "time": "0.002931000000ms"

           }

         ]

       }

     ]

   }

}

 

 

Profile API响应说明

上面的响应显示的是单个分片。每个分片都被分配一个唯一的ID,ID的格式是[nodeID][indexName][shardID]。现在在"shards"数组里还有另外三个元素,它们是:

  1. query
  2. rewrrite_time
  3. collector

Query

Query 段由构成Query的元素以及它们的时间信息组成。Profile API结果中Query 部分的基本组成是:

  1. query type – 它向我们显示了哪种类型的查询被触发。此处是布尔值。因为多个关键字匹配查询被分成两个布尔查询。

     

  2. lucene – 该字段显示启动查询的lucene方法。这里是 "brand:levi brand:goals"

  3. time – lucene 执行此查询所用的时间。单位是毫秒。

  4. breakdown – 有关查询的更详细的细节,主要与lucene参数有关。
  5. children – 具有多个关键字的查询被拆分成相应术语的布尔查询,每个查询都作为单独的查询来执行。每个子查询的详细信息将填充到Profile API输出的子段中。在上面的章节中,可以看到第一个子元素查询是"levi",下面给出查询时间和其他breakdown参数等详细信息。同样,对于第二个关键字,有一个名为"goals"的子元素具有与其兄弟相同的信息。从查询中的子段中,我们可以得到关于哪个搜索项在总体搜索中造成最大延迟的信息。

Rewrite Time

由于多个关键字会分解以创建个别查询,所以在这个过程中肯定会花费一些时间。将查询重写一个或多个组合查询的时间被称为“重写时间”。(以纳秒为单位)。

Collectors

在Lucene中,收集器是负责收集原始结果,收集和组合结果,执行结果排序等的过程。例如,在上面的执行的查询中,当查询语句中给出size:0时,使用的收集器是"totalHitCountCollector"。这只返回搜索结果的数量(search_count),不返回文档。此外,收集者所用的时间也一起给出了。

总结

在这篇博客中,我们看到Profile API非常有用,它让我们清楚地看到查询时间。通过向我们提供有关子查询的详细信息,清楚地知道在那个环节查询慢,这是非常有用的。另外,API返回结果中,关于Lucene的详细信息也让我们深入了解到 elasticsearch 是如何执行查询的。

参考:

http://cwiki.apachecn.org/display/Elasticsearch/Profile+API

相关文章:

  1. elasticsearch indices.recovery 流程分析与速度优化
<think>好的,用户想优化Elasticsearch集群的查询性能,但他们的日志量小。首先,我需要回顾一下之前提供的引用内容,看看有哪些优化点可以应用。 根据引用[1],Elasticsearch在大规模应用中需要优化集群性能,但用户这里的日志量小,可能不需要大规模的调整。不过架构概述里的内容可能还是有用的,比如分片设置和节点角色分配。 引用[2]提到了查询缓存的配置,默认是堆内存的10%,用户可以考虑调整这个参数,尤其是如果他们的查询重复率高的话。不过日志量小,可能缓存的效果有限,但设置合理的值还是有帮助的。 引用[3]详细讲了慢查询日志的配置,这对排查具体慢查询问题非常有用。用户应该启用日志,找出具体的慢查询,然后针对性地优化查询语句或者索引结构。 引用[4]提到了分片分配和恢复的问题,虽然用户日志量小,但如果分片设置不合理,比如过多或过少,也会影响性能。需要检查分片数量和大小是否合适,避免未分配分片的问题。 接下来,用户提到日志量小,可能意味着他们的数据量不大,所以硬件资源可能不是瓶颈,但配置不当仍然会导致查询。可能需要从以下几个方面入手: 1. **分片优化**:小数据量下,过多的分片会增加开销。建议每个索引的主分片数根据数据量调整,可能1-2个主分片足够,副本分片根据节点数设置,确保高可用即可。 2. **索引设计**:是否使用了合适的字段类型,比如keyword和text的区别,避免不必要的分词。对于不需要分析的字段,使用keyword类型,并禁用norms和index_options,减少索引大小,提升查询速度。 3. **查询优化**:避免使用高开销的查询,如通配符查询、模糊查询。使用filter上下文利用缓存,因为filter的结果会被缓存。合并多个查询,使用bool查询替代单独的term查询。 4. **缓存调整**:调整查询缓存和分片请求缓存的大小,尤其是如果查询重复率高的话。但小数据量下可能效果有限,需要根据实际情况测试。 5. **日志分析**:启用日志,找出具体哪些查询,然后分析原因。可能需要对某些字段添加索引或者优化查询语句。 6. **硬件和JVM配置**:确保内存足够,避免swap。JVM堆内存设置合理,通常不超过32GB,避免指针压缩失效。使用SSD硬盘提升IO性能。 可能还需要检查集群的健康状态,是否有未分配的分片,或者节点负载不均衡的情况。使用Cluster Allocation Explain API查看分片分配情况,必要时手动调整。 另外,用户提到日志量小,可能集群规模也小,节点数量少。需要确认节点角色是否合理,比如专用主节点、数据节点、协调节点分离,但小集群可能节点数量不足以分离角色,这时候需要权衡。 最后,建议用户先进行基准测试,记录当前的查询性能,然后逐一应用优化措施,对比效果,找到最适合他们场景的配置。</think>以下是针对Elasticsearch集群查询性能优化的系统性解决方案(日志量小场景): ### 一、索引设计优化 1. **分片策略调整** - 单索引建议控制在$10GB-50GB$,主分片数根据数据量设置为$1-2$个 - 副本数设置为$1$(可通过API动态调整): ```json PUT /my_index/_settings { "number_of_replicas": 1 } ``` - 使用`_shrink` API合并小分片[^4] 2. **字段类型优化** ```json PUT /my_index { "mappings": { "properties": { "log_message": { "type": "text", "norms": false, // 禁用评分因子 "index_options": "freqs" }, "timestamp": { "type": "date", "format": "epoch_millis" } } } } ``` ### 二、查询执行优化 1. **查询语句优化** - 使用`filter`代替`query`上下文: ```json GET /_search { "query": { "bool": { "filter": [{ "range": { "timestamp": { "gte": "now-1d/d" }} }] } } } ``` - 避免使用`wildcard`查询,改用`keyword`类型+精确匹配 2. **分片请求控制** ```json GET /_search?preference=_shards:1 // 指定分片查询 ``` ### 三、集群配置优化 1. **缓存配置调整**(elasticsearch.yml)[^2]: ```yaml indices.queries.cache.size: 20% # 提升查询缓存 indices.request.cache.size: 5% # 分片请求缓存 ``` 2. **JVM参数优化** - 堆内存设置为物理内存的$50%$,不超过$32GB$ - 添加GC参数: ```yaml -XX:+UseG1GC -XX:MaxGCPauseMillis=200 ``` ### 四、诊断工具使用 1. **日志配置**[^3]: ```json PUT /_template/slowlog_template { "template": "*", "settings": { "index.search.slowlog.threshold.query.warn": "500ms", "index.search.slowlog.threshold.query.info": "200ms" } } ``` 2. **Profile API定位瓶颈**: ```json GET /my_index/_search { "profile": true, "query": {...} } ``` ### 五、硬件优化建议 1. 使用SSD存储介质 2. 单节点内存不低于$8GB$ 3. 设置`vm.swappiness=1`避免交换
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值