聚合结果分析:
聚合查询,结果包括两部分,一个是hits,一个是aggregations.
另一部分:是查询情况显示,包括:took(查询消耗时间),time_out(是否超时),_shards(查询了几个分片,是否失败等)
“hits”:聚合查询的结果,默认按照分值排序。显示的每条内容,可以通过_source,store等参数控制
在使用json查询es时,最外层size控制了显示的条目数
"aggregations": 存储了聚合的最终结果
聚合查询的准确性分析
es在执行分桶查询时,会在每个分片下执行所有查询内容,最后在一个分片中将所有内容汇总,返回给客户端。这个过程中会存在数据误差。
es默认,每个分片返回的是前十条数据,以下为举例分析方便,自定义了一下返回结果,并做分析
如:使用term实现分组查询,并计算每个组的数目时,假如设定每个分片返回3条最多的数据,并最后汇总。
假定第一个分片依次是:
A:30 B:28 C:22 D:20 E:20
假定第二个分片依次是:
A:58 B:26 C:15 D:14 E:14
假定第三个分片依次是:
E:35 B:26 D:18 C:14 A:10
如以上数据:
假如每个分片返回最多的前三条数据,并送到汇总分片,去获取排名前三的:则排序依次是A:88 B:80 C:37
假如每个分片返回最多前的四条数据,并送到汇总分片,去获取排名前三的:则排序依次是A:88 B:80 D:52
假如每个分片返回最多前的五条数据,并送到汇总分片,去获取排名前三的:则排序依次是A:98 B:80 E:69
实际应用中,可以允许每个分片返回更多的数据,但相对而言,花费的时间就够多
聚合和分页查询
由已上可知,对聚合后的数据,做分页查询,是无法支持的。
聚合能够实现前十,前一百,前一千,但是无法支持分页,因为分页查询的本质是将所有数据进行统合后分析。其中第一个问题就是,每个分片之间会生成大量的结果,造成性能大幅降低。但是倘若不传全部的数据,而只是传递部分数据,则会造成,排名在后的,可能出现数据比排名靠前的还要大。因为本身聚合就有一定的误差。
MYSQL查询结果:
以下由于es中数据,比mysql少几条,因此使用id来控制范围,这个无关紧要
mysql> SELECT nid, count(nid) as cnt from node_file_viruses WHERE find_time >=1567624289 AND find_time < 1568229089 AND virus_findby =20 AND id< 3782070 GROUP BY nid ORDER BY cnt desc;
+-----+-----+
| nid | cnt |
+-----+-----+
| 426 | 440 |
| 422 | 432 |
| 428 | 425 |
| 430 | 424 |
| 427 | 424 |
| 424 | 423 |
| 359 | 408 |
| 366 | 406 |
| 360 | 403 |
| 421 | 403 |
| 429 | 399 |
| 365 | 398 |
| 423 | 395 |
| 425 | 385 |
| 362 | 384 |
| 364 | 383 |
| 363 | 381 |
| 367 | 374 |
| 361 | 373 |
| 410 | 372 |
| 411 | 372 |
| 412 | 367 |
| 368 | 363 |
| 413 | 360 |
| 414 | 356 |
| 417 | 354 |
| 415 | 346 |
| 409 | 346 |
| 416 | 345 |
| 401 | 317 |
| 418 | 316 |
| 389 | 305 |
| 390 | 304 |
| 394 | 299 |
| 392 | 296 |
| 405 | 289 |
| 404 | 288 |
| 385 | 286 |
| 399 | 284 |
| 403 | 283 |
| 406 | 283 |
| 402 | 283 |
| 400 | 282 |
| 391 | 279 |
| 388 | 276 |
| 407 | 276 |
| 386 | 273 |
| 398 | 272 |
| 393 | 266 |
| 387 | 254 |
| 374 | 113 |
| 378 | 106 |
| 381 | 103 |
| 375 | 98 |
| 380 | 98 |
| 377 | 97 |
| 376 | 91 |
| 382 | 89 |
| 379 | 87 |
| 373 | 81 |
+-----+-----+
60 rows in set (1.02 sec)
ES默认查询结果:
[root@jiangmin ~]# curl -X GET 'localhost:9200/node_file_viruses/_search?pretty' -H 'Content-Type:application/json' -d '{
> "size":0, -------------> 定义满足以下聚合查询的返回数据
> "aggs":{
> "seven_range":{
> "range":{
> "field": "find_time",
> "ranges": [ {"from": 1567624289,"to":1568229089} ]
> },
> "aggs":{
> "client":{
> "terms":{
> "size": 10, ---》定义每个分片,返回的聚合数量,默认从大到小排序
> "field": "nid"
> }
> }
> }
> }
> },
> "query":{
> "bool":{
> "must":[
> {
> "term":{
> "virus_findby": 20
> }
> }
> ]
> }
> }
> }'
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 252359,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"seven_range" : {
"buckets" : [
{
"key" : "1.567624289E9-1.568229089E9",
"from" : 1.567624289E9,
"to" : 1.568229089E9,
"doc_count" : 18215,
"client" : {
"doc_count_error_upper_bound" : 347,
"sum_other_doc_count" : 14157,
"buckets" : [
{
"key" : 426,
"doc_count" : 440
},
{
"key" : 422,
"doc_count" : 432
},
{
"key" : 430,
"doc_count" : 424
},
{
"key" : 359,
"doc_count" : 408
},
{
"key" : 366,
"doc_count" : 406
},
{
"key" : 421,
"doc_count" : 403
},
{
"key" : 423,
"doc_count" : 395
},
{
"key" : 425,
"doc_count" : 385
},
{
"key" : 362,
"doc_count" : 384
},
{
"key" : 363,
"doc_count" : 381
}
]
}
}
]
}
}
}
通过以上对比发现,桶聚合和Mysql group by的值有差距,如nid428的数据,使用es查询时就出现遗漏。
分析可知道,es中的数据,是存在不同的分片中,当要查询数据时,各个分片,按照聚合原则,取出最多的前十条,最后将所有分片的数据整合,得到最终的数据。
这里,可能出现了nid=428的数据,在某个分片或者多个分片中,排序不在前十,因此最终汇总时,出现数据偏差。
可以通过修改聚合时,每个桶的排序数,而得到正确数据
通过修改es聚合排序数量,得到更精确的数据
以下,通过修改term聚合的返回数量,得到了与mysql查询更接近的结果
[root@jiangmin ~]# curl -X GET 'localhost:9200/node_file_viruses/_search?pretty' -H 'Content-Type:application/json' -d '{
> "size":0,
> "aggs":{
> "seven_range":{
> "range":{
> "field": "find_time",
> "ranges": [ {"from": 1567624289,"to":1568229089} ]
> },
> "aggs":{
> "client":{
> "terms":{
> "size": 20,
> "field": "nid"
> }
> }
> }
> }
> },
> "query":{
> "bool":{
> "must":[
> {
> "term":{
> "virus_findby": 20
> }
> }
> ]
> }
> }
> }'
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 252359,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"seven_range" : {
"buckets" : [
{
"key" : "1.567624289E9-1.568229089E9",
"from" : 1.567624289E9,
"to" : 1.568229089E9,
"doc_count" : 18215,
"client" : {
"doc_count_error_upper_bound" : 280,
"sum_other_doc_count" : 10183,
"buckets" : [
{
"key" : 426,
"doc_count" : 440
},
{
"key" : 422,
"doc_count" : 432
},
{
"key" : 428,
"doc_count" : 425
},
{
"key" : 427,
"doc_count" : 424
},
{
"key" : 430,
"doc_count" : 424
},
{
"key" : 424,
"doc_count" : 423
},
{
"key" : 359,
"doc_count" : 408
},
{
"key" : 366,
"doc_count" : 406
},
{
"key" : 360,
"doc_count" : 403
},
{
"key" : 421,
"doc_count" : 403
},
{
"key" : 429,
"doc_count" : 399
},
{
"key" : 365,
"doc_count" : 398
},
{
"key" : 423,
"doc_count" : 395
},
{
"key" : 425,
"doc_count" : 385
},
{
"key" : 362,
"doc_count" : 384
},
{
"key" : 364,
"doc_count" : 383
},
{
"key" : 363,
"doc_count" : 381
},
{
"key" : 367,
"doc_count" : 374
},
{
"key" : 361,
"doc_count" : 373
},
{
"key" : 410,
"doc_count" : 372
}
]
}
}
]
}
}
}