Elasticsearch慢查询故障诊断

最近在作ES搜索调优,看了一些lucene搜索的文档和代码,本文用于总结调优过程当中学到的知识和本身的思考。node

在抓到ES慢查询以后,会经过profile或者kibana的Search Profiler console查看具体慢在了哪里。通常在执行profile search以前,须要稍微改变query语句里的查询内容,防止cache影响测试效果。算法

profile主要包括shard级别的query耗时、query语句rewrite耗时以及最终lucene collector的耗时。elasticsearch

通常主要关注query的耗时,profile返回的query部分详细的展现了被rewrite后的查询语句以及每一个子查询的耗时。包括子查询的类型(type),子查询语句(description),子查询耗时(time_in_nanos)和一个breakdown集合包含了lucene segements search各阶段的耗时。从这个breakdown集合中能比较清晰的看到耗时的缘由,固然,前提是要理解breakdown里每一个指标表明什么意思和内部的实现逻辑。测试

breakdown里的主要指标及lucene中的实现:ui

build_scorer:构造一个scorer的耗时。scorer主要用于对matching的doc进行打分和排序。build_scorer内部构造了迭代器,这个迭代器能够遍历全部matched document,构造迭代器是很是耗时的操做,由于涉及到对各子查询的docId结果集构造倒排链或bitset,而且作conjunction生成最终可被迭代的docId bitset或倒排链。大多数查询主要耗时在这一步。orm

next_doc: 寻找下一个匹配的document Id。这里keyword, text等文本类型的字段会利用skipList,数值类型的数据会利用Tree结构快速找的下一个匹配的docoument Id。同时,这里会记录该doc命中的子查询数量,用于最终的min_should_match之类的过滤。排序

advance: 相似于一个low level的next_doc。并非全部的query都能实现next_doc,好比must查询走的advance去找下一个匹配的文档。ip

score: 记录socrer中对文档打分的耗时,经过Freq,normal等数据结合tf-idf等算法计算出得分。资源

match: 记录第二阶段打分的耗时。有些查询须要两阶段打分,好比短语查询(phrase query) "chinese love china", 第一阶段先找全部包含“chinese”、“love”、“china”三个term的文档。第二阶段再在第一阶段匹配到到的全部文档中计算“chinese”,"love","china"三个单词的位置和顺序是否知足条件,这一操做很是耗时,因此经过第一阶段缩小匹配文档的范围。文档

create_weight: 建立weight过程的耗时,weight就至关于lucene查询的context,里面包含了query,collector,indexreader等。

*_count: 记录方法调用次数,好比next_doc_count:2,表明next_doc方法被调用了两次。

除了query过程的详细统计,还包括:

rewrite_time: query语句被重写的耗时,lucene本身维护了一套查询语句重写逻辑,好比terms查询中若是要查询的terms个数小于16,会被重写成多个TermQuery作or结合;若是大于16会被重写成TermInSetQuery。

collector: query数据收集阶段的各类指标。包括query用到的collector的个数,类型和耗时。ES默认使用的是SimpleTopScoreDocCollector。lucene的collector主要经过reduce方法对每一个segment上匹配的结果进行合并和排序,返回topN。

 

故障诊断过程当中,除了经过profile API定位慢查询,也须要关注ES集群的总体资源使用状况,好比data node的CPU, Mem, 磁盘IO是否有瓶颈,单节点shard个数是否过多等。通常能够经过cerebro或者elasticsearch_exporter+Prometheus来监控集群状态, 也能够经过ES API查看相关指标。

相关文章
相关标签/搜索