日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Elasticsearch深入理解(九)——三种分页方式选取

發(fā)布時間:2023/12/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Elasticsearch深入理解(九)——三种分页方式选取 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、from + size

ElasticSearch默認采用的分頁方式是from + size的形式,在深度分頁的情況下,這種使用方式的效率是非常低的,比如我們執(zhí)行如下查詢:

1

2

3

4

5

6

7

8

GET /student/student/_search

{

??"query":{

????"match_all": {}

??},

??"from":5000,

??"size":10

}

以上DSL語句執(zhí)行后,ElasticSearch需要在各個分片上匹配排序并得到5010條數(shù)據(jù),協(xié)調(diào)節(jié)點拿到這些數(shù)據(jù)再進行排序處理,然后結(jié)果集中取最后10條數(shù)據(jù)返回。

這樣的深度分頁的效率非常低,因為我們只需要查詢10條數(shù)據(jù),而ElasticSearch則需要對from + size條數(shù)據(jù)進行排序處理后返回。

其次:ElasticSearch為了性能,限制了分頁的深度,目前ElasticSearch支持的最大的查詢長度是max_result_window = 10000;也就是說我們不能分頁到10000條數(shù)據(jù)以上。

例如:9990+10 = 10000,此時可以執(zhí)行分頁查詢。

但是,當9991+10 > 10000,此時執(zhí)行查詢的返回為:

二、scroll(游標)

? ? ? ? 相對于from和size的分頁來說,使用scroll可以模擬一個傳統(tǒng)數(shù)據(jù)的游標,記錄當前讀取的文檔信息位置。這個分頁的用法,不是為了實時查詢數(shù)據(jù),而是為了一次性查詢大量的數(shù)據(jù)(甚至是全部的數(shù)據(jù))。

傳統(tǒng)數(shù)據(jù)庫游標:

? ? ??游標(cursor)是系統(tǒng)為用戶開設(shè)的一個數(shù)據(jù)緩沖區(qū),存放SQL語句的執(zhí)行結(jié)果。每個游標區(qū)都有一個名字,用戶可以用SQL語句逐一從游標中獲取記錄,并賦給主變量,交由主語言進一步處理。就本質(zhì)而言,游標實際上是一種能從包括多條數(shù)據(jù)記錄的結(jié)果集中每次提取一條記錄的機制。游標是一段私有的SQL工作區(qū),也就是一段內(nèi)存區(qū)域,用于暫時存放受SQL語句影響到的數(shù)據(jù)。通俗理解就是將受影響的數(shù)據(jù)暫時放到了一個內(nèi)存區(qū)域的虛表中,而這個虛表就是游標。

ElasticSearch scroll:

? ? ? 使用scroll滾動搜索,可以先搜索一批數(shù)據(jù),然后下次再搜索一批數(shù)據(jù),以此類推,直到搜索出全部的數(shù)據(jù)。scroll搜索會在第一次搜索的時候,保存一個當時的視圖快照,之后只會基于該舊的視圖快照提供數(shù)據(jù)搜索,如果這個期間數(shù)據(jù)變更,是不會讓用戶看到的。每次發(fā)送scroll請求,我們還需要指定一個scroll參數(shù),指定一個時間窗口,每次搜索請求只要在這個時間窗口內(nèi)能完成就可以了。

? ? ??一個滾屏搜索允許我們做一個初始階段搜索并且持續(xù)批量從Elasticsearch里拉取結(jié)果直到?jīng)]有結(jié)果剩下。

? ? ? 滾屏搜索會及時制作快照。這個快照不會包含任何在初始階段搜索請求后對index做的修改。它通過將舊的數(shù)據(jù)文件保存在手邊,所以可以保護index的樣子看起來像搜索開始時的樣子。這樣將使得我們無法得到用戶最近的更新行為

scroll的使用:

執(zhí)行如下curl,每次請求兩條。可以定制 scroll = 1m意味著該窗口過期時間為1分鐘。

1

2

3

4

5

6

7

GET /student/student/_search?scroll=1m

{

??"query":{

????"match_all": {}

??},

??"size":2

}

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

36

37

38

39

40

41

42

43

{

??"_scroll_id"?:?"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAR-lFlBWekUzVGlUUjhXQ09KQ2dwLTA1eFEAAAAAAAEfphZQVnpFM1RpVFI4V0NPSkNncC0wNXhRAAAAAAABH6cWUFZ6RTNUaVRSOFdDT0pDZ3AtMDV4UQ==",

??"took"?:?15,

??"timed_out"?:?false,

??"_shards"?: {

????"total"?:?3,

????"successful"?:?3,

????"skipped"?:?0,

????"failed"?:?0

??},

??"hits"?: {

????"total"?:?4,

????"max_score"?:?1.0,

????"hits"?: [

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"2",

????????"_score"?:?1.0,

????????"_source"?: {

??????????"id"?:?2,

??????????"name"?:?"仙道彰",

??????????"age"?:?17,

??????????"gender"?:?"男",

??????????"address"?:?"神奈川縣陵南高中"

????????}

??????},

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"4",

????????"_score"?:?1.0,

????????"_source"?: {

??????????"id"?:?4,

??????????"name"?:?"赤木剛憲",

??????????"age"?:?20,

??????????"address"?:?"東京大學(xué)",

??????????"gender"?:?"男"

????????}

??????}

????]

??}

}

可以看到在返回結(jié)果中,存在一個很重要的_scroll_id,在后面的請求中,都需要在帶著這個_scroll_id去請求。如下:

1

2

3

4

5

GET /_search/scroll

{

??"scroll":"1m",

??"scroll_id":"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAR-lFlBWekUzVGlUUjhXQ09KQ2dwLTA1eFEAAAAAAAEfphZQVnpFM1RpVFI4V0NPSkNncC0wNXhRAAAAAAABH6cWUFZ6RTNUaVRSOFdDT0pDZ3AtMDV4UQ=="

}

執(zhí)行一次,得到結(jié)果:

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

36

37

38

39

40

41

42

43

{

??"_scroll_id"?:?"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAASI_FlBWekUzVGlUUjhXQ09KQ2dwLTA1eFEAAAAAAAEiQRZQVnpFM1RpVFI4V0NPSkNncC0wNXhRAAAAAAABIkAWUFZ6RTNUaVRSOFdDT0pDZ3AtMDV4UQ==",

??"took"?:?3,

??"timed_out"?:?false,

??"_shards"?: {

????"total"?:?3,

????"successful"?:?3,

????"skipped"?:?0,

????"failed"?:?0

??},

??"hits"?: {

????"total"?:?4,

????"max_score"?:?1.0,

????"hits"?: [

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"3",

????????"_score"?:?1.0,

????????"_source"?: {

??????????"id"?:?3,

??????????"name"?:?"赤木晴子",

??????????"age"?:?17,

??????????"gender"?:?"女",

??????????"address"?:?"神奈川縣湘北高中"

????????}

??????},

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"1",

????????"_score"?:?1.0,

????????"_source"?: {

??????????"id"?:?1,

??????????"name"?:?"櫻木花道",

??????????"age"?:?18,

??????????"address"?:?"神奈川縣湘北高中",

??????????"gender"?:?"男"

????????}

??????}

????]

??}

}

再執(zhí)行一次,得到結(jié)果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

{

??"_scroll_id"?:?"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAASI_FlBWekUzVGlUUjhXQ09KQ2dwLTA1eFEAAAAAAAEiQRZQVnpFM1RpVFI4V0NPSkNncC0wNXhRAAAAAAABIkAWUFZ6RTNUaVRSOFdDT0pDZ3AtMDV4UQ==",

??"took"?:?1,

??"timed_out"?:?false,

??"_shards"?: {

????"total"?:?3,

????"successful"?:?3,

????"skipped"?:?0,

????"failed"?:?0

??},

??"hits"?: {

????"total"?:?4,

????"max_score"?:?1.0,

????"hits"?: [ ]

??}

}

現(xiàn)在student這個索引中共有4條數(shù)據(jù),id分別為 1, 2, 3, 4。當我們使用 scroll 查詢第3次的時候,返回結(jié)果為kong。這時我們就知道已經(jīng)結(jié)果集已經(jīng)匹配完了。

三、search_after

? ? ? from + size的分頁方式雖然是最靈活的分頁方式,但是當分頁深度達到一定程度將會產(chǎn)生深度分頁的問題。scroll能夠解決深度分頁的問題,但是其無法實現(xiàn)實時查詢,即當scroll_id生成后無法查詢到之后數(shù)據(jù)的變更,因為其底層原理是生成數(shù)據(jù)的快照。這時 search_after應(yīng)運而生。其是在es-5.X之后才提供的。

? ? ??search_after 是一種假分頁方式,根據(jù)上一頁的最后一條數(shù)據(jù)來確定下一頁的位置,同時在分頁請求的過程中,如果有索引數(shù)據(jù)的增刪改查,這些變更也會實時的反映到游標上。為了找到每一頁最后一條數(shù)據(jù),每個文檔必須有一個全局唯一值,官方推薦使用 _id 作為全局唯一值,但是只要能表示其唯一性就可以。

執(zhí)行如下查詢:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

GET /student/student/_search

{

??"query":{

????"match_all": {}

??},

??"size":2,

??"sort": [

????{

??????"id": {

????????"order":?"desc"

??????}

????}

??]

}

結(jié)果為:

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

36

37

38

39

40

41

42

43

44

45

46

47

48

{

??"took"?:?1,

??"timed_out"?:?false,

??"_shards"?: {

????"total"?:?3,

????"successful"?:?3,

????"skipped"?:?0,

????"failed"?:?0

??},

??"hits"?: {

????"total"?:?4,

????"max_score"?:?null,

????"hits"?: [

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"4",

????????"_score"?:?null,

????????"_source"?: {

??????????"id"?:?4,

??????????"name"?:?"赤木剛憲",

??????????"age"?:?20,

??????????"address"?:?"東京大學(xué)",

??????????"gender"?:?"男"

????????},

????????"sort"?: [

??????????4

????????]

??????},

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"3",

????????"_score"?:?null,

????????"_source"?: {

??????????"id"?:?3,

??????????"name"?:?"赤木晴子",

??????????"age"?:?17,

??????????"gender"?:?"女",

??????????"address"?:?"神奈川縣湘北高中"

????????},

????????"sort"?: [

??????????3

????????]

??????}

????]

??}

}

可以看到結(jié)果集中的??"sort" : [3] ,將當前結(jié)果集中sort的值,作為下一次查詢search_after的參數(shù):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

GET /student/student/_search

{

??"query":{

????"match_all": {}

??},

??"size":2,

??"sort": [

????{

??????"_id": {

????????"order":?"desc"

??????}

????}

??],

??"search_after":[3]

}

得到結(jié)果為:

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

36

37

38

39

40

41

42

43

44

45

46

47

48

{

??"took"?:?1,

??"timed_out"?:?false,

??"_shards"?: {

????"total"?:?3,

????"successful"?:?3,

????"skipped"?:?0,

????"failed"?:?0

??},

??"hits"?: {

????"total"?:?4,

????"max_score"?:?null,

????"hits"?: [

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"4",

????????"_score"?:?null,

????????"_source"?: {

??????????"id"?:?4,

??????????"name"?:?"赤木剛憲",

??????????"age"?:?20,

??????????"address"?:?"東京大學(xué)",

??????????"gender"?:?"男"

????????},

????????"sort"?: [

??????????4

????????]

??????},

??????{

????????"_index"?:?"student",

????????"_type"?:?"student",

????????"_id"?:?"3",

????????"_score"?:?null,

????????"_source"?: {

??????????"id"?:?3,

??????????"name"?:?"赤木晴子",

??????????"age"?:?17,

??????????"gender"?:?"女",

??????????"address"?:?"神奈川縣湘北高中"

????????},

????????"sort"?: [

??????????3

????????]

??????}

????]

??}

}

這樣我們就使用search_after方式實現(xiàn)了分頁查詢。

四、三種分頁方式的比較

分頁方式性能優(yōu)點缺點場景
from + size靈活性好,實現(xiàn)簡單深度分頁問題數(shù)據(jù)量比較小,能容忍深度分頁問題
scroll解決了深度分頁問題

無法反應(yīng)數(shù)據(jù)的實時性(快照版本)

維護成本高,需要維護一個 scroll_id

海量數(shù)據(jù)的導(dǎo)出,需要查詢海量結(jié)果集的數(shù)據(jù)

search_after

性能最好

不存在深度分頁問題

能夠反映數(shù)據(jù)的實時變更

實現(xiàn)復(fù)雜,需要有一個全局唯一的字段

連續(xù)分頁的實現(xiàn)會比較復(fù)雜,因為每一次查詢都需要上次查詢的結(jié)果

海量數(shù)據(jù)的分頁

總結(jié)

以上是生活随笔為你收集整理的Elasticsearch深入理解(九)——三种分页方式选取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。