聚合結果分析:
聚合查詢,結果包括兩部分,一個是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
}
]
}
}
]
}
}
}