Elasticsearch(一)架构及一般性应用
?
首先,當(dāng)我們對(duì)記錄進(jìn)行修改時(shí),es會(huì)把數(shù)據(jù)同時(shí)寫(xiě)到內(nèi)存緩存區(qū)和translog中。而這個(gè)時(shí)候數(shù)據(jù)是不能被搜索到的,只有數(shù)據(jù)形成了segmentFile,才會(huì)被搜索到。默認(rèn)情況下,es每隔一秒鐘執(zhí)行一次refresh,可以通過(guò)參數(shù)index.refresh_interval來(lái)修改這個(gè)刷新間隔或者搜索時(shí)加上?refresh=wait_for強(qiáng)制刷新,但是會(huì)造成刷新頻次過(guò)高會(huì)造成性能下降,表示如果1秒內(nèi)有請(qǐng)求立即更新并可見(jiàn),執(zhí)行refresh主要做三件事:
1、所有在內(nèi)存緩沖區(qū)中的文檔被寫(xiě)入到一個(gè)新的segment中,但是沒(méi)有調(diào)用fsync,因此內(nèi)存中的數(shù)據(jù)可能丟失;
2、segment被打開(kāi)使得里面的文檔能夠被搜索到;
3、清空內(nèi)存緩沖區(qū);
translog的相當(dāng)于事務(wù)日志,記錄著所有對(duì)Elasticsearch的操作記錄,也是對(duì)Elasticsearch的一種備份。因?yàn)椴⒉皇菍?xiě)到segment就表示數(shù)據(jù)落到磁盤了,實(shí)際上segment是存儲(chǔ)在系統(tǒng)緩存(page cache)中的,只有達(dá)到一個(gè)周期或者數(shù)據(jù)量達(dá)到一定值,才會(huì)flush到磁盤上。這個(gè)時(shí)候如果系統(tǒng)內(nèi)存中的segment丟失,是可以通過(guò)translog來(lái)恢復(fù)的。這個(gè)flush過(guò)程主要做了三件事:
1、往磁盤里寫(xiě)入commit point信息。
2、文件系統(tǒng)中的segment,fsync到磁盤。
3、清空translog文件。
translog可以保證緩存中的segment的恢復(fù),但translog也不是實(shí)時(shí)也磁盤的,也就是說(shuō),內(nèi)存中的translog丟了的話,也會(huì)有丟失數(shù)據(jù)的可能。所以translog也要進(jìn)行flush。translog的flush主要有三個(gè)條件:
1、可以設(shè)置是否在某些操作之后進(jìn)行強(qiáng)制flush,比如索引的刪除或批量請(qǐng)求之后。
2、translog大小超過(guò)512mb或者超過(guò)三十分鐘會(huì)強(qiáng)制對(duì)segment進(jìn)行flush,隨后會(huì)強(qiáng)制對(duì)translog進(jìn)行flush,這種情況緩存中的translog在flush之后會(huì)被清空。
3、默認(rèn)5s,會(huì)強(qiáng)制對(duì)translog進(jìn)行flush。最小值可配置100ms。
6.3版本顯示保留translog文件的最長(zhǎng)持續(xù)時(shí)間。默認(rèn)為12h。
參考官網(wǎng):Translog | Elasticsearch Guide [6.3] | Elastic
refresh,flush 和fsync的區(qū)別
1.refresh是將緩沖隊(duì)列buffer里數(shù)據(jù)刷入文件緩沖系統(tǒng)生成索引文件segement,該segement數(shù)據(jù)才能被查詢到,保證查詢屬性可見(jiàn)
2.flush是將索引文件segement數(shù)據(jù)持久化到硬盤(觸發(fā)機(jī)制是translog文件超過(guò)512mb或者30分鐘強(qiáng)強(qiáng)制刷新segement)
3.fsyncd是將translog 持久化到硬盤(每5秒執(zhí)行一次) 寫(xiě)入translog其實(shí)也是在內(nèi)存中。translog 和segement持久化到硬盤是兩回事。
持久化的translog文件中存的是所有索引成segement的數(shù)據(jù)但還未持久化到硬盤的內(nèi)容,一旦segement持久化到硬盤translog會(huì)清空。
參考:https://elasticsearch.cn/question/3847
索引存儲(chǔ)方式
Elasticsearch是一個(gè)建立在全文搜索引擎庫(kù)Apache Lucene 基礎(chǔ)上的分布式搜索引擎,Lucene最早的版本是2000年發(fā)布的,距今已經(jīng)18年,是當(dāng)今最先進(jìn),最高效的全功能開(kāi)源搜索引擎框架。
Lucene
Lucene中包含了四種基本數(shù)據(jù)類型,分別是:
- Index:索引,由很多的Document組成。
- Document:由很多的Field組成,是Index和Search的最小單位。
- Field:由很多的term組成,包括field_name和field_value。
- Term:由很多的字節(jié)組成,可以分詞,分詞之后每個(gè)詞即為一個(gè)term。term是索引的最小單元。
上述四種類型在Elasticsearch中同樣存在,意思也一樣。
Lucene中存儲(chǔ)的索引主要分為三種類型:
- Invert Index,即倒排索引。通過(guò)term可以快速查找到包含該term的doc_id。如果Field配置分詞,則分詞后的每個(gè)term都會(huì)進(jìn)入倒排索引,如果Field不指定分詞,那該Field的value值則會(huì)作為一個(gè)term進(jìn)入倒排。(這里需要注意的是term的長(zhǎng)度是有限制的,如果對(duì)一個(gè)Field不采取分詞,那么不建議該Field存儲(chǔ)過(guò)長(zhǎng)的值。關(guān)于term超長(zhǎng)處理)
- DocValues,即正排索引。采用的是類似數(shù)據(jù)庫(kù)的列式存儲(chǔ)。對(duì)于一些特殊需求的字段可以選擇這種索引方式。
- Store,即原文。存儲(chǔ)整個(gè)完整Document的原始信息。
倒排索引是lucene的核心索引類型,采用鏈表的數(shù)據(jù)結(jié)構(gòu),倒排索引中的key就是一個(gè)term,value就是以doc_id形成的鏈表結(jié)構(gòu)。
Term ? ? ?Doc_1 ? ? ?Doc_2
-------------------------
Quick ? ? ?| ? ? ? ? ? ? ? | ?X
The ? ? ? ? | ? X ? ? ? ? ?|
brown ? ? | ? X ? ? ? ? ?| ?X
dog ? ? ? ? | ? X ? ? ? ? ?|
dogs ? ? ? | ? ? ? ? ? ? ? ?| ?X
fox ? ? ? ? ?| ? X ? ? ? ? ?|
foxes ? ? ?| ? ? ? ? ? ? ? ?| ?X
in ? ? ? ? ? ?| ? ? ? ? ? ? ? ?| ?X
jumped ?| ? X ? ? ? ? ?| ? ?
lazy ? ? ? ?| ? X ? ? ? ? ?| ?X
leap ? ? ? ?| ? ? ? ? ? ? ? ?| ?X
over ? ? ? ?| ? X ? ? ? ? ?| ?X
quick ? ? ?| ? X ? ? ? ? ?|
summer ?| ? ? ? ? ? ? ? | ?X
the ? ? ? ? ?| ? X ? ? ? ? ?|
------------------------
現(xiàn)在,如果我們想搜索 quick brown ,我們只需要查找包含每個(gè)詞條的文檔:
Term ? ? ?Doc_1 ? ? ?Doc_2
-------------------------
brown ? | ? X ? ? ? ? ?| ?X
quick ? ?| ? X ? ? ? ? ? |
------------------------
Total ? ? | ? 2 ? ? ? ? ? | ?1
這里分別匹配到了doc1和doc2,但是doc1匹配度要高于doc2。
倒排索引中的value有四種存儲(chǔ)類型:
- DOCS:只存儲(chǔ)doc_id。
- DOCS_AND_FREQS:存儲(chǔ)doc_id和詞頻(Term Freq)。
- DOCS_AND_FREQS_AND_POSITIONS:存儲(chǔ)doc_id、詞頻(Term Freq)和位置。
- DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS:存儲(chǔ)doc_id、詞頻(Term Freq)、位置和偏移(offset)。
DocValues
正排索引類似關(guān)系型數(shù)據(jù)庫(kù)的存儲(chǔ)模式,作用是通過(guò)doc_id和field_name可以快速定位到指定doc的特定字段值。DocValues的key是doc_id+field_name,value是field_value。
ES默認(rèn)會(huì)對(duì)所有字段進(jìn)行正排索引,但并不是所有字段都需要DocValues。所以合理配置DocValues可以節(jié)省存儲(chǔ)空間。DocValues的使用場(chǎng)景一般是:需要針對(duì)某個(gè)Field排序、聚合、過(guò)濾和script。
Store
存儲(chǔ)的是Document的完整信息,包括所有field_name和field_value。Store的key是doc_id,value是field_name+field_value。對(duì)于上訴中需要聚合和排序的Field并沒(méi)有開(kāi)啟DocValues的情況,依然可以實(shí)現(xiàn)排序和聚合,會(huì)從Store中獲取要排序聚合的字段值。
Elasticsearch在Lucene基礎(chǔ)上的改變
Lucene本身不支持分布式,Elasticsearch通過(guò)_routing實(shí)現(xiàn)分布式的架構(gòu)。我們可以通過(guò)_routing來(lái)實(shí)現(xiàn)不同doc分布在不同的Shard上,我們可以自己定義也可以系統(tǒng)自動(dòng)分配。對(duì)于指定_routing的插入和查詢,性能上會(huì)更好。
Lucene中沒(méi)有主鍵索引,并且id是在Segment中唯一。那么Elasticsearch是如何實(shí)現(xiàn)doc_id唯一?Elasticsearch中有個(gè)系統(tǒng)字段_id,來(lái)決定doc唯一。_id是在用戶可見(jiàn)層度上的id值,實(shí)際上Elasticsearch內(nèi)部會(huì)把_id存儲(chǔ)成_uid(_uid =index_type + '#' + _id)。_uid只會(huì)存儲(chǔ)倒排和原文,目的就是為了通過(guò)id可以快速索引到doc。這里需要注意的是,在Elasticsearch6.x版本以后,一個(gè)index只支持一個(gè)type,這也就意味著_id和_uid概念幾乎相同。以后的版本中,Elasticsearch會(huì)取消type。
Elasticsearch通過(guò)_version字段來(lái)保證文檔的一致性。更多關(guān)于文檔的一致性和鎖機(jī)制的參考:ElasticSearch干貨(一):鎖機(jī)制
Elasticsearch通過(guò)_source字段來(lái)存儲(chǔ)doc原文。這個(gè)字段非常重要。Lucene的update是覆蓋,是不支持針對(duì)doc中特定字段進(jìn)行修改的。但Elasticsearch支持對(duì)特定字段的修改,就是基于_source字段實(shí)現(xiàn)的。關(guān)于Elasticsearch的update詳細(xì)內(nèi)容,參考:ElasticSearch干貨(二):index、create、update區(qū)別
Elasticsearch通過(guò)_field_names字段來(lái)判斷doc中是否存在某個(gè)字段。_field_names的存儲(chǔ)形式為倒排,可以快速判斷出是否包含某個(gè)field_name。
Lucene中Segment一旦創(chuàng)建不可修改。那么Elasticsearch如何實(shí)現(xiàn)實(shí)時(shí)修改并索引數(shù)據(jù)的呢?詳細(xì)參考:ElasticSearch原理(三):寫(xiě)入流程
關(guān)于原理和索引先介紹到這里,主要這里還是聚焦與如何實(shí)現(xiàn)幾個(gè)關(guān)鍵需求?
ES延時(shí)問(wèn)題
默認(rèn)情況下,es每隔一秒鐘執(zhí)行一次refresh,可以通過(guò)參數(shù)index.refresh_interval來(lái)修改這個(gè)刷新間隔或者搜索時(shí)加上?refresh=wait_for強(qiáng)制刷新,但是會(huì)造成刷新頻次過(guò)高會(huì)造成性能下降,表示如果1秒內(nèi)有請(qǐng)求立即更新并可見(jiàn)。另外由于沒(méi)有生成segment,也就是說(shuō)不能通過(guò)索引來(lái)獲取,但是可以通過(guò)直接get by id來(lái)獲取單條記錄。
搜索(同時(shí)實(shí)現(xiàn)精確查詢和模糊查詢和組合查詢)
ES的搜索是分2個(gè)階段進(jìn)行的,即Query階段和Fetch階段。? Query階段比較輕量級(jí),通過(guò)查詢倒排索引,獲取滿足查詢結(jié)果的文檔ID列表。? 而Fetch階段比較重,需要將每個(gè)shard的結(jié)果取回,在協(xié)調(diào)結(jié)點(diǎn)進(jìn)行全局排序。? 通過(guò)From+size這種方式分批獲取數(shù)據(jù)的時(shí)候,隨著from加大,需要全局排序并丟棄的結(jié)果數(shù)量隨之上升,性能越來(lái)越差。
1、精確查詢
在elasticsearch 中輸入查詢條件,一般會(huì)匹配到很多結(jié)果,是因?yàn)閍nalyzer的存在:
Each element in the result represents a single term:
{"tokens": [{"token": "text","start_offset": 0,"end_offset": 4,"type": "<ALPHANUM>","position": 1},{"token": "to","start_offset": 5,"end_offset": 7,"type": "<ALPHANUM>","position": 2},{"token": "analyze","start_offset": 8,"end_offset": 15,"type": "<ALPHANUM>","position": 3}] }必須要將字段設(shè)置為not_analyzed?才可以,如下:
PUT /my_store { "mappings" : { "products" : { "properties" : { "productID" : { "type" : "string", "index" : "not_analyzed" } } } } }
2、es組合多個(gè)條件進(jìn)行查詢
1、must、should
GET /test_index/_search
{
"query": {
"bool": {
"must": { "match": { "name": "tom" }},
"should": [
{ "match": { "hired": true }},
{ "bool": {
"must": { "match": { "personality": "good" }},
"must_not": { "match": { "rude": true }}
}}
],
"minimum_should_match": 1
}
}
}
在es中,使用組合條件查詢是其作為搜索引擎檢索數(shù)據(jù)的一個(gè)強(qiáng)大之處,在前幾篇中,簡(jiǎn)單演示了es的查詢語(yǔ)法,但基本的增刪改查功能并不能很好的滿足復(fù)雜的查詢場(chǎng)景,比如說(shuō)我們期望像mysql那樣做到拼接復(fù)雜的條件進(jìn)行查詢?cè)撊绾巫瞿?#xff1f;es中有一種語(yǔ)法叫bool,通過(guò)在bool里面拼接es特定的語(yǔ)法可以做到大部分場(chǎng)景下復(fù)雜條件的拼接查詢,也叫復(fù)合查詢
首先簡(jiǎn)單介紹es中常用的組合查詢用到的關(guān)鍵詞,
filter:過(guò)濾,不參與打分
must:如果有多個(gè)條件,這些條件都必須滿足 and與
should:如果有多個(gè)條件,滿足一個(gè)或多個(gè)即可 or或
must_not:和must相反,必須都不滿足條件才可以匹配到 !非
發(fā)生 描述
must
該條款(查詢)必須出現(xiàn)在匹配的文件,并將有助于得分。
filter
子句(查詢)必須出現(xiàn)在匹配的文檔中。然而不像 must查詢的分?jǐn)?shù)將被忽略。Filter子句在過(guò)濾器上下文中執(zhí)行,這意味著評(píng)分被忽略,子句被考慮用于高速緩存。
should
子句(查詢)應(yīng)該出現(xiàn)在匹配的文檔中。如果 bool查詢位于查詢上下文中并且具有mustor filter子句,則bool即使沒(méi)有should查詢匹配,文檔也將匹配該查詢 。在這種情況下,這些條款僅用于影響分?jǐn)?shù)。如果bool查詢是過(guò)濾器上下文 或者兩者都不存在,must或者filter至少有一個(gè)should查詢必須與文檔相匹配才能與bool查詢匹配。這種行為可以通過(guò)設(shè)置minimum_should_match參數(shù)來(lái)顯式控制 。
must_not
子句(查詢)不能出現(xiàn)在匹配的文檔中。子句在過(guò)濾器上下文中執(zhí)行,意味著評(píng)分被忽略,子句被考慮用于高速緩存。因?yàn)橛?jì)分被忽略,0所有文件的分?jǐn)?shù)被返回。
3、模糊查詢
前綴查詢:匹配包含具有指定前綴的項(xiàng)(not analyzed)的字段的文檔。前綴查詢對(duì)應(yīng)?Lucene?的?PrefixQuery?。
案例 GET /_search { "query": {"prefix" : { "user" : { "value" : "ki", "boost" : 2.0 } }} }正則表達(dá)式查詢:egexp?(正則表達(dá)式)查詢?cè)试S您使用正則表達(dá)式進(jìn)行項(xiàng)查詢。有關(guān)支持的正則表達(dá)式語(yǔ)言的詳細(xì)信息,請(qǐng)參閱正則表達(dá)式語(yǔ)法。第一個(gè)句子中的 “項(xiàng)查詢” 意味著?Elasticsearch?會(huì)將正則表達(dá)式應(yīng)用于由該字段生成的項(xiàng),而不是字段的原始文本。注意:?regexp?(正則表達(dá)式)查詢的性能很大程度上取決于所選的正則表達(dá)式。匹配一切像?“.*”?,是非常慢的,使用回顧正則表達(dá)式也是如此。如果可能,您應(yīng)該嘗試在正則表達(dá)式開(kāi)始之前使用長(zhǎng)前綴。通配符匹配器?“.*?+”?將主要降低性能。
案例 GET /_search {"query": {"regexp":{"name.first":{"value":"s.*y","boost":1.2}}} } ‘通配符查詢:匹配與通配符表達(dá)式具有匹配字段的文檔(not analyzed)。支持的通配符是 “*”,它匹配任何字符序列(包括空字符);還有 “?”,它匹配任何單個(gè)字符。請(qǐng)注意,此查詢可能很慢,因?yàn)樗枰鄠€(gè)項(xiàng)。為了防止極慢的通配符查詢,通配符項(xiàng)不應(yīng)以通配符 “*” 或 “?” 開(kāi)頭。通配符查詢對(duì)應(yīng)?Lucene?的?WildcardQuery?。
案例 GET /_search {"query": {"wildcard" : { "user" : { "value" : "ki*y", "boost" : 2.0 } }} }###模糊查詢數(shù)據(jù)量越大效率越低,當(dāng)查詢內(nèi)容較多,數(shù)據(jù)量較大時(shí)建議將該字段設(shè)置成text進(jìn)行分詞,然后通過(guò)match進(jìn)行匹配。
排序與相關(guān)性
默認(rèn)情況下,返回的結(jié)果是按照 相關(guān)性 進(jìn)行排序的——最相關(guān)的文檔排在最前。 在本章的后面部分,我們會(huì)解釋 相關(guān)性 意味著什么以及它是如何計(jì)算的, 不過(guò)讓我們首先看看 sort 參數(shù)以及如何使用它。
1、排序
為了按照相關(guān)性來(lái)排序,需要將相關(guān)性表示為一個(gè)數(shù)值。在 Elasticsearch 中, 相關(guān)性得分 由一個(gè)浮點(diǎn)數(shù)進(jìn)行表示,并在搜索結(jié)果中通過(guò) _score 參數(shù)返回, 默認(rèn)排序是 _score 降序。
有時(shí),相關(guān)性評(píng)分對(duì)你來(lái)說(shuō)并沒(méi)有意義。例如,下面的查詢返回所有 user_id 字段包含 1 的結(jié)果:
GET /_search {"query" : {"bool" : {"filter" : {"term" : {"user_id" : 1}}}} }里沒(méi)有一個(gè)有意義的分?jǐn)?shù):因?yàn)槲覀兪褂玫氖?filter (過(guò)濾),這表明我們只希望獲取匹配 user_id: 1 的文檔,并沒(méi)有試圖確定這些文檔的相關(guān)性。 實(shí)際上文檔將按照隨機(jī)順序返回,并且每個(gè)文檔都會(huì)評(píng)為零分。
1.1、按照字段的值排序
在這個(gè)案例中,通過(guò)時(shí)間來(lái)對(duì) tweets 進(jìn)行排序是有意義的,最新的 tweets 排在最前。 我們可以使用 sort 參數(shù)進(jìn)行實(shí)現(xiàn):
GET /_search {"query" : {"bool" : {"filter" : { "term" : { "user_id" : 1 }}}},"sort": { "date": { "order": "desc" }} }1.2、多級(jí)排序
假定我們想要結(jié)合使用 date 和 _score 進(jìn)行查詢,并且匹配的結(jié)果首先按照日期排序,然后按照相關(guān)性排序:
GET /_search {"query" : {"bool" : {"must": { "match": { "tweet": "manage text search" }},"filter" : { "term" : { "user_id" : 2 }}}},"sort": [{ "date": { "order": "desc" }},{ "_score": { "order": "desc" }}] }排序條件的順序是很重要的。結(jié)果首先按第一個(gè)條件排序,僅當(dāng)結(jié)果集的第一個(gè) sort 值完全相同時(shí)才會(huì)按照第二個(gè)條件進(jìn)行排序,以此類推。
多級(jí)排序并不一定包含 _score 。你可以根據(jù)一些不同的字段進(jìn)行排序, 如地理距離或是腳本計(jì)算的特定值。
1.3、字段多值的排序
一種情形是字段有多個(gè)值的排序, 需要記住這些值并沒(méi)有固有的順序;一個(gè)多值的字段僅僅是多個(gè)值的包裝,這時(shí)應(yīng)該選擇哪個(gè)進(jìn)行排序呢?
對(duì)于數(shù)字或日期,你可以將多值字段減為單值,這可以通過(guò)使用 min 、 max 、 avg 或是 sum 排序模式 。 例如你可以按照每個(gè) date 字段中的最早日期進(jìn)行排序,通過(guò)以下方法:
"sort": {"dates": {"order": "asc","mode": "min"} }- 更多詳情清參考此文;
如何在elasticsearch里面使用分頁(yè)功能
from + size 淺分頁(yè)
"淺"分頁(yè)可以理解為簡(jiǎn)單意義上的分頁(yè)。它的原理很簡(jiǎn)單,就是查詢前20條數(shù)據(jù),然后截?cái)嗲?0條,只返回10-20的數(shù)據(jù)。這樣其實(shí)白白浪費(fèi)了前10條的查詢。
GET test_dev/_search {"query": {"bool": {"filter": [{"term": {"age": 28}}]}},"size": 10,"from": 20,"sort": [{"timestamp": {"order": "desc"},"_id": {"order": "desc"}}] }其中,from定義了目標(biāo)數(shù)據(jù)的偏移值,size定義當(dāng)前返回的數(shù)目。默認(rèn)from為0,size為10,即所有的查詢默認(rèn)僅僅返回前10條數(shù)據(jù)。
在這里有必要了解一下from/size的原理:
因?yàn)閑s是基于分片的,假設(shè)有5個(gè)分片,from=100,size=10。則會(huì)根據(jù)排序規(guī)則從5個(gè)分片中各取回100條數(shù)據(jù)數(shù)據(jù),然后匯總成500條數(shù)據(jù)后選擇最后面的10條數(shù)據(jù)。
做過(guò)測(cè)試,越往后的分頁(yè),執(zhí)行的效率越低。總體上會(huì)隨著from的增加,消耗時(shí)間也會(huì)增加。而且數(shù)據(jù)量越大,就越明顯!
es默認(rèn)的from+size的分頁(yè)方式返回的結(jié)果數(shù)據(jù)集不能超過(guò)1萬(wàn)點(diǎn),超過(guò)之后返回的數(shù)據(jù)越多性能就越低;
這是因?yàn)閑s要計(jì)算相似度排名,需要排序整個(gè)整個(gè)結(jié)果集,假設(shè)我們有一個(gè)index它有5個(gè)shard,現(xiàn)在要讀取1000到1010之間的這10條數(shù)據(jù),es內(nèi)部會(huì)在每個(gè)shard上讀取1010條數(shù)據(jù),然后返回給計(jì)算節(jié)點(diǎn),這里有朋友可能問(wèn)為啥不是10條數(shù)據(jù)而是1010條呢?這是因?yàn)槟硞€(gè)shard上的10條數(shù)據(jù),可能還沒(méi)有另一個(gè)shard上top10之后的數(shù)據(jù)相似度高,所以必須全部返回,然后在計(jì)算節(jié)點(diǎn)上,重新對(duì)5050條數(shù)據(jù)進(jìn)行全局排序,最后在選取top 10出來(lái),這里面排序是非常耗時(shí)的,所以這個(gè)數(shù)量其實(shí)是指數(shù)級(jí)增長(zhǎng)的,到后面分頁(yè)數(shù)量越多性能就越下降的厲害,而且大量的數(shù)據(jù)排序會(huì)占用jvm的內(nèi)存,很有可能就OOM了,這也是為什么es默認(rèn)不允許讀取超過(guò)1萬(wàn)條數(shù)據(jù)的原因。?
scroll 深分頁(yè)
from+size查詢?cè)?0000-50000條數(shù)據(jù)(1000到5000頁(yè))以內(nèi)的時(shí)候還是可以的,但是如果數(shù)據(jù)過(guò)多的話,就會(huì)出現(xiàn)深分頁(yè)問(wèn)題。
為了解決上面的問(wèn)題,elasticsearch提出了一個(gè)scroll滾動(dòng)的方式。
scroll 類似于sql中的cursor,使用scroll,每次只能獲取一頁(yè)的內(nèi)容,然后會(huì)返回一個(gè)scroll_id。根據(jù)返回的這個(gè)scroll_id可以不斷地獲取下一頁(yè)的內(nèi)容,所以scroll并不適用于有跳頁(yè)的情景。
然后我們可以通過(guò)數(shù)據(jù)返回的_scroll_id讀取下一頁(yè)內(nèi)容,每次請(qǐng)求將會(huì)讀取下10條數(shù)據(jù),直到數(shù)據(jù)讀取完畢或者scroll_id保留時(shí)間截止:
GET _search/scroll {"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......","scroll": "5m" }注意:請(qǐng)求的接口不再使用索引名了,而是 _search/scroll,其中GET和POST方法都可以使用。
scroll刪除
根據(jù)官方文檔的說(shuō)法,scroll的搜索上下文會(huì)在scroll的保留時(shí)間截止后自動(dòng)清除,但是我們知道scroll是非常消耗資源的,所以一個(gè)建議就是當(dāng)不需要了scroll數(shù)據(jù)的時(shí)候,盡可能快的把scroll_id顯式刪除掉。
清除指定的scroll_id:
DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....清除所有的scroll:
DELETE _search/scroll/_allsearch_after 深分頁(yè)
scroll 的方式,官方的建議不用于實(shí)時(shí)的請(qǐng)求(一般用于數(shù)據(jù)導(dǎo)出),因?yàn)槊恳粋€(gè) scroll_id 不僅會(huì)占用大量的資源,而且會(huì)生成歷史快照,對(duì)于數(shù)據(jù)的變更不會(huì)反映到快照上。
search_after 分頁(yè)的方式是根據(jù)上一頁(yè)的最后一條數(shù)據(jù)來(lái)確定下一頁(yè)的位置,同時(shí)在分頁(yè)請(qǐng)求的過(guò)程中,如果有索引數(shù)據(jù)的增刪改查,這些變更也會(huì)實(shí)時(shí)的反映到游標(biāo)上。但是需要注意,因?yàn)槊恳豁?yè)的數(shù)據(jù)依賴于上一頁(yè)最后一條數(shù)據(jù),所以無(wú)法跳頁(yè)請(qǐng)求。
為了找到每一頁(yè)最后一條數(shù)據(jù),每個(gè)文檔必須有一個(gè)全局唯一值,官方推薦使用 _uid 作為全局唯一值,其實(shí)使用業(yè)務(wù)層的 id 也可以。
GET test_dev/_search {"query": {"bool": {"filter": [{"term": {"age": 28}}]}},"size": 20,"from": 0,"sort": [{"timestamp": {"order": "desc"},"_id": {"order": "desc"}}] }使用sort返回的值搜索下一頁(yè):
GET test_dev/_search {"query": {"bool": {"filter": [{"term": {"age": 28}}]}},"size": 10,"from": 0,"search_after": [1541495312521,"d0xH6GYBBtbwbQSP0j1A"],"sort": [{"timestamp": {"order": "desc"},"_id": {"order": "desc"}}] } </div>只是整合記錄少有原創(chuàng)
總結(jié)
以上是生活随笔為你收集整理的Elasticsearch(一)架构及一般性应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 网关和BFF是如何演进出来的?
- 下一篇: 微服务架构下的安全认证与鉴权