参考:

https://alexmarquardt.com/2020/10/21/elasticsearch-too-many-script-compilations/

https://github.com/elastic/beats/issues/9600

定位问题

a.字面意思是,ElasticSearch5分钟内执行脚本编译超过75个,编译太多而拒绝编译。编译是非常耗时的,这是ES的自我保护功能。

b.我的操作是希望实现先以索引位置正序排序,再以长度排序, 最后再进行普通排序. 排序使用的脚本 如下

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
"sort": [
{
"_script": {
"type": "number",
"script": {
"source": """def val = doc['字段名'].value;
int slashIndex = val.indexOf('值');
return slashIndex;
"""
},
"order": "asc"
}
},
{
"_script": {
"type": "number",
"script": {
"source": "doc['字段名'].value.length()"
},
"order": "asc"
}
},
{
"字段名": {
"order": "asc"
}
}
]

临时解决办法(配置每5分钟500)

从 7.9 开始默认启用上下文。但是,如果当前未启用上下文(出于某种原因),则可以使用以下命令启用它们

1
2
3
4
5
6
PUT _cluster/settings
{
"transient": {
"script.max_compilations_rate": "use-context"
}
}

如果使用了上下文,可以使用以下命令查看

1
GET /_nodes/stats?filter_path=nodes.*.script_cache.contexts

transient参数只会持续到es重新启动

1
2
3
4
5
6
PUT _cluster/settings
{
"transient": {
"script.context.number_sort.max_compilations_rate": "500/5m"
}
}

persistent(持久)大多数用例可能此参数是首选

1
2
3
4
5
6
7
PUT _cluster/settings
{
"persistent": {
"script.context.number_sort.max_compilations_rate": "500/5m"
}
}

检查

1
GET _cluster/settings

解决办法

max_compilations_rate参数不宜设置过大, 脚本编译是极其吃资源的一个操作

7.10.4源码

所以我们可以将脚本参数写进params里, 以避免重复编译, 如下

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
"sort": [
{
"_script": {
"type": "number",
"script": {
"params": {
"field": "字段名",
"val": "值"
},
"source": """def val = doc[params.field].value;
int slashIndex = val.indexOf(params.val);
return slashIndex;
"""
},
"order": "asc"
}
},
{
"_script": {
"type": "number",
"script": {
"params": {
"field": "字段名"
},
"source": "doc[params.field].value.length()"
},
"order": "asc"
}
},
{
"字段名": {
"order": "asc"
}
}
]