设置参数 `node.name` 可以自定义 Elasticsearch 节点的名字。 此条 Tips 由 medcl 贡献。

filter 查询的顺序

匿名 | 发布于2017年09月27日 | 阅读数:6581

es版本: 2.3
routing _id 用的是
user_id

doc量在3亿左右
正常的获取一个用户的文档查询
GET /index/type/{user_id}

响应是非常快的, 在10ms左右
但是, 当使用如下的查询的时候, 发现速度非常慢(200到300ms)
[code]POST /index/type/_search?routing={user_id}
{
"query": {
"bool": {
"filter": [
{
"term": {
"user_id": 12345
}
}
],
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"term": {
"field_a": 1
}
},
{
"range": {
"field_b": {
"gt": 3
}
}
},
{
"range": {
"field_c": {
"lte": 20
}
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"field_a": 1
}
},
{
"range": {
"field_b": {
"lte": 3
}
}
},
{
"term": {
"field_d": 0
}
},
{
"range": {
"field_e": {
"lte": 4
}
}
}
]
}
}
]
}
},
"terminate_after": 1,
"size": 0
}
[/code]
简化下查询如下:
[code]{
"query": {
"bool": {
"filter": [
{
"term": {
"user_id": 12345
}
}
],
"minimum_should_match": 1,
"should": [...] # 这里没有在上面 filter 的基础上进行匹配吗?
}
},
"terminate_after": 1,
"size": 0
}
[/code]
使用了 profile 发现,
should
里面的查询, 没有使用到上面
filter
的结果, 耗时了200+ms


因为如果使用了, 不会这么慢


我的理解是. filter + term + user_id 相当于一次 get id 请求, 为什么增加一些额外的查询后(比如上面的 should 查询), 会导致性能差这么多呢?
还是我的使用姿势有问题?
或者是 filter 的顺序导致的(查了下, 应该不是, es 会自动优化顺序)
谢谢
已邀请:

Cheetah

赞同来自: rank6 novia

你得搞清楚这里的原理,bool filter查询并不是筛选,而是一个个的bitset,然后来做交集--已经明白了吧,实际userid并无缩小范围的作用
如果想达到你的要求,请使用andfilter或者orfilter,这种是筛选的,但是无缓存
所以各有各得优势,自己根据业务选择吧

kennywu76 - Wood

赞同来自: rank6

每个filter执行过程都是独立,不依赖其他filter的执行结果的,因此没有先后顺序的概念。 不过之后需要合并这些filter的结果是,会有先后顺序。这个过程会选择较短的文档列表做起点,通过跳表在这些列表之间相互skip得到最后的结果。 
 
所以性能主要是取决于各个filter执行的快慢,以及包含文档最少的filter里文档id的数量。如果那些bool query内部的filter,match的doc都比较多,那么合并过程可能会比较长,影响性能。

novia - 1&0

赞同来自:

去掉这个minimum_should_match这个参数看看

strglee

赞同来自:

GET /index/type/{user_id}
这种方式es 会根据id直接找到对应的分片,所以会很快
SEARCH query 
这种方式即使数据只有一条,es也会将这个查询分发到各个分片,然后再聚合结果,当然就慢了。
 
 

rank6

赞同来自:

 
@Cheetah
感谢回复.
我查了下, 目前 andfilter 指的应该是 bool filter 里的 must 查询吧?
意思是这样改吗?
原来是:
[code]{
"query": {
"bool": {
"filter": [
{
"term": {
"user_id": 12345
}
}
],
"minimum_should_match": 1,
"should": [...]
}
},
"terminate_after": 1,
"size": 0
}
[/code]
修改成:
[code]{
"query": {
"bool": {
"must": [
{
"term": {
"user_id": 12345
},
'bool': {
'should': [...]
}
}
],
}
},
"terminate_after": 1,
"size": 0
}
[/code]

 

要回复问题请先登录注册