两小时 Elasticsearch 性能优化,直接把慢查询干团灭了
问题:慢查询
搜索平台的公共集群,由于业务众多,对业务的es查询语法缺少约束,导致问题频发。业务可能写了一个巨大的查询直接把集群打挂掉,但是我们平台人力投入有限,也不可能一条条去审核业务的es查询语法,只能通过后置的手段去保证整个集群的稳定性,通过slowlog分析等,下图中cpu已经100%了。
昨天刚好手头有一点点时间,就想着能不能针对这些情况,把影响最坏的业务抓出来,进行一些改善,于是昨天花了2小时分析了一下,找到了一些共性的问题,可以通过平台来很好的改善这些情况。
首先通过slowlog抓到一些耗时比较长的查询,例如下面这个索引的查询耗时基本都在300ms以上:
{
"from": 0,
"size": 200,
"timeout": "60s",
"query": {
"bool": {
"must": \[
{
"match": {
"source": {
"query": "5",
"operator": "OR",
"prefix\_length": 0,
"fuzzy\_transpositions": true,
"lenient": false,
"zero\_terms\_query": "NONE",
"auto\_generate\_synonyms\_phrase\_query": "false",
"boost": 1
}
}
},
{
"terms": {
"type": \[
"21"
\],
"boost": 1
}
},
{
"match": {
"creator": {
"query": "0d754a8af3104e978c95eb955f6331be",
"operator": "OR",
"prefix\_length": 0,
"fuzzy\_transpositions": "true",
"lenient": false,
"zero\_terms\_query": "NONE",
"auto\_generate\_synonyms\_phrase\_query": "false",
"boost": 1
}
}
},
{
"terms": {
"status": \[
"0",
"3"
\],
"boost": 1
}
},
{
"match": {
"isDeleted": {
"query": "0",
"operator": "OR",
"prefix\_length": 0,
"fuzzy\_transpositions": "true",
"lenient": false,
"zero\_terms\_query": "NONE",
"auto\_generate\_synonyms\_phrase\_query": "false",
"boost": 1
}
}
}
\],
"adjust\_pure\_negative": true,
"boost": 1
}
},
"\_source": {
"includes": \[
\],
"excludes": \[\]
}
}
这个查询比较简单,翻译一下就是:
SELECT guid FROM xxx WHERE source=5 AND type=21 AND creator=0d754a8af3104e978c95eb955f6331be AND status in (0,3) AND isDeleted=0;
慢查询分析
这个查询问题还挺多的,不过不是今天的重点。比如这里面不好的一点是还用了模糊查询fuzzy_transpositions,也就是查询ab的时候,ba也会被命中,其中的语法不是今天的重点,可以自行查询,我估计这个是业务用了SDK自动生成的,里面很多都是默认值。
第一反应当然是用filter来代替match查询,一来filter可以缓存,另外避免这种无意义的模糊匹配查询,但是这个优化是有限的,并不是今天讲解的关键点,先忽略。
1、错用的数据类型
我们通过kibana的profile来进行分析,耗时到底在什么地方?es有一点就是开源社区很活跃,文档齐全,配套的工具也非常的方便和齐全。
可以看到大部分的时间都花在了PointRangQuery里面去了,这个是什么查询呢?为什么这么耗时呢?这里就涉及到一个es的知识点,那就是对于integer这种数字类型的处理。在es2.x的时代,所有的数字都是按keyword处理的,每个数字都会建一个倒排索引,这样查询虽然快了,但是一旦做范围查询的时候。比如 type