99久久国产露脸精品麻豆,欧美日韩精品小说,亚洲免费在线美女视频,国产三级中文字幕,91极品国产情侣高潮对白,国产亚洲一区二区三区不卡片,欧美jizz精品欧美性,久久国产精品久久国产片

ElasticSearch 深度分頁(yè)解決方案

袁志蒙 2828次瀏覽

摘要:Elasticsearch分頁(yè)方式有三種,分別是“from + size 淺分頁(yè)”、 “scroll” 和 “search_after”方式,本文詳細(xì)介紹一下這三種分頁(yè)的使用場(chǎng)景,elasticsearch默認(rèn)采用的分頁(yè)方式是from+size的形式,但是在深度分頁(yè)的情況下...

Elasticsearch分頁(yè)方式有三種,分別是“from + size 淺分頁(yè)”、 “scroll” 和 “search_after”方式。

一、from + size 淺分頁(yè)

"淺"分頁(yè)可以理解為簡(jiǎn)單意義上的分頁(yè),它的原理很簡(jiǎn)單,就是查詢前20條數(shù)據(jù),然后截?cái)嗲?0條,只返回10-20的數(shù)據(jù),這樣其實(shí)白白浪費(fèi)了前10條的查詢。

在這里有必要了解一下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ù),所以越往后的分頁(yè),執(zhí)行的效率越低??傮w上會(huì)隨著from的增加,消耗時(shí)間也會(huì)增加。而且數(shù)據(jù)量越大,就越明顯!

除了效率上的問(wèn)題,還有一個(gè)無(wú)法解決的問(wèn)題是,es 目前支持最大的 skip 值是 max_result_window ,默認(rèn)為 10000 。也就是當(dāng) from + size > max_result_window 時(shí),es 將返回錯(cuò)誤,max_result_window 調(diào)大方式,治標(biāo)不治本,不建議使用。

二、scroll 深分頁(yè)

為了滿足深度分頁(yè)的場(chǎng)景,es 提供了 scroll 的方式進(jìn)行分頁(yè)讀取。原理上是對(duì)某次查詢生成一個(gè)游標(biāo) scroll_id , 后續(xù)的查詢只需要根據(jù)這個(gè)游標(biāo)去取數(shù)據(jù),直到結(jié)果集中返回的 hits 字段為空,就表示遍歷結(jié)束。scroll_id 的生成可以理解為建立了一個(gè)臨時(shí)的歷史快照,在此之后的增刪改查等操作不會(huì)影響到這個(gè)快照的結(jié)果。

scroll 類似于sql中的cursor,使用scroll,每次只能獲取一頁(yè)的內(nèi)容,然后會(huì)返回一個(gè)scroll_id。根據(jù)返回的這個(gè)scroll_id可以不斷地獲取下一頁(yè)的內(nèi)容,所以scroll并不適用于有跳頁(yè)的情景。

scroll使用過(guò)程:

先獲取第一個(gè) scroll_id,url 參數(shù)包括 /index/_type/ 和 scroll,scroll 字段指定了scroll_id 的有效生存期,以分鐘為單位,過(guò)期之后會(huì)被es自動(dòng)清理。如果文檔不需要特定排序,可以指定按照文檔創(chuàng)建的時(shí)間返回會(huì)使迭代更高效。

$client = ClientBuilder::create()->build();
$params = array(
    'index' => 'product-*',
    '_source' => 'shopname,number,price',
    "scroll" => "1m",
    "size" => 10
);

//scroll=1m 表示設(shè)置 scroll_id 保留1分鐘可用。使用scroll必須要將from設(shè)置為0或者不寫。
// 返回結(jié)果
array(5) {
  ["_scroll_id"] => string(64) "cXVlcnlBbmRGZXRjaDsxOzg3OTA4NDpTQzRmWWkwQ1Q1bUlwMjc0WmdIX2ZnOzA7"
  ["took"] => int(1)
  ["timed_out"] => bool(false)
  ["_shards"] => array(3) {
    ["total"] => int(1)
    ["successful"] => int(1)
    ["failed"] => int(0)
  }
  ["hits"] => array(10) {
  	  ...
  }
}


然后我們可以通過(guò)數(shù)據(jù)返回的 _scroll_id 讀取下一頁(yè)內(nèi)容,如果srcoll_id 的生存期很長(zhǎng),那么每次返回的 scroll_id 都是一樣的,直到該 scroll_id 過(guò)期,才會(huì)返回一個(gè)新的 scroll_id。請(qǐng)求指定的 scroll_id 時(shí)就不需要 /index/_type 等信息了。每讀取一頁(yè)都會(huì)重新設(shè)置 scroll_id 的生存時(shí)間,所以這個(gè)時(shí)間只需要滿足讀取當(dāng)前頁(yè)就可以,不需要滿足讀取所有的數(shù)據(jù)的時(shí)間,1分鐘足以。

$client = ClientBuilder::create()->build();
$res = $client->scroll(array('scroll_id' => $scroll_id, 'scroll' => '1m'));

一個(gè)完整的 es scroll深度翻頁(yè)P(yáng)HP代碼:

public function lists(){
	$page = $_POST['page'] ?? 1;
	$size = $_POST['size'] ?? 10;
	$params = array(
	  'index' => 'yzm_users',
	  'scroll' => '1m',
	  'size' => $size
	);
	$params['body'] = array(
	  //查詢條件
	);
	$docs = $this->client->search($params);
	$scroll_id = $docs['_scroll_id'];
	
	if($page == 1 ){
	  return_json(array(
	    'status' => 1,
	    'data' => $docs['hits']['hits']
	  ));
	}

	$i = 1;
	while ($i < $page) {
	  $response = $this->client->scroll(
		  array(
		    'scroll_id' => $scroll_id,
		    'scroll' => '1m'
		  )
		);

		if (count($response['hits']['hits']) > 0) {
		  $scroll_id = $response['_scroll_id'];
		} else {
		  break;
		}
	  $i++;
	}

	return_json(array(
	  'status' => 1,
	  'data' => $response['hits']['hits']
	));
}

三、search_after 深分頁(yè)

上述的 scroll search 的方式,官方的建議并不是用于實(shí)時(shí)的請(qǐng)求,因?yàn)槊恳粋€(gè) scroll_id 不僅會(huì)占用大量的資源(特別是排序的請(qǐng)求),而且是生成的歷史快照,對(duì)于數(shù)據(jù)的變更不會(huì)反映到快照上。這種方式往往用于非實(shí)時(shí)處理大量數(shù)據(jù)的情況,比如要進(jìn)行數(shù)據(jù)遷移或者索引變更之類的。那么在實(shí)時(shí)情況下如果處理深度分頁(yè)的問(wèn)題呢?es 給出了 search_after 的方式,這是在 >= 5.0 版本才提供的功能。

search_after 分頁(yè)的方式和 scroll 有一些顯著的區(qū)別,首先它是根據(jù)上一頁(yè)的最后一條數(shù)據(jù)來(lái)確定下一頁(yè)的位置,同時(shí)在分頁(yè)請(qǐng)求的過(guò)程中,如果有索引數(shù)據(jù)的增刪改查,這些變更也會(huì)實(shí)時(shí)的反映到游標(biāo)上。

為了找到每一頁(yè)最后一條數(shù)據(jù),每個(gè)文檔必須有一個(gè)全局唯一值,這種分頁(yè)方式其實(shí)和目前 moa 內(nèi)存中使用rbtree 分頁(yè)的原理一樣,官方推薦使用 _uid 作為全局唯一值,其實(shí)使用業(yè)務(wù)層的 id 也可以。

search_after使用過(guò)程:

第一頁(yè)的請(qǐng)求和正常的請(qǐng)求一樣。

$client = ClientBuilder::create()->build();
$params = array(
    'index' => 'product-*',
    '_source' => 'shopname,number,price',
    'body' => [
        'sort' => [
            'timestamp' =>['order'=>'asc'],
            '_id' =>['order'=>'desc'],
        ]
    ],
    "size" => 10
);

//search_after必須使用唯一值進(jìn)行排序才可以
// 返回結(jié)果
array(4) {
  ["took"] => int(1753)
  ["timed_out"] => bool(false)
  ["_shards"] => array(4) {
    ["total"] => int(3)
    ["successful"] => int(3)
    ["skipped"] => int(0)
    ["failed"] => int(0)
  }
  ["hits"] => array(3) {
    ["total"] => array(2) {
      ["value"] => int(10000)
      ["relation"] => string(3) "gte"
    }
    ["max_score"] => NULL
    ["hits"] => array(10) {
      [0] => array(6) {
        ["_index"] => string(16) "product"
        ["_type"] => string(7) "_doc"
        ["_id"] => string(20) "FHsS6XwBEqA0wm2Y5INV"
        ["_score"] => NULL
        ["_source"] => array(7) {
		....
        }
        ["sort"] => array(2) {
          [0] => int(1635997891112)
          [1] => string(20) "FHsS6XwBEqA0wm2Y5INV"
        }
      }
    }
  }
}

第二頁(yè)的請(qǐng)求,使用第一頁(yè)返回結(jié)果的最后一個(gè)數(shù)據(jù)的 sort 值,加上 search_after 字段來(lái)取下一頁(yè)。注意,使用 search_after 的時(shí)候要將 from參數(shù)必須被設(shè)置成 0 或 -1 (當(dāng)然你也可以不設(shè)置這個(gè)from參數(shù))。

$client = ClientBuilder::create()->build();
$params = array(
    'index' => 'product-*',
    '_source' => 'shopname,number,price',
    'body' => [
        'search_after' => [
        	'1635997891112',
        	'FHsS6XwBEqA0wm2Y5INV'
        ],
        'sort' => [
            'timestamp' =>['order'=>'asc'],
            '_id' =>['order'=>'desc'],
        ]
    ],
    "size" => 10
);
$res = $client->search($params);

search_afterscroll 非常相似,同樣適用于深度分頁(yè) + 排序,因?yàn)槊恳豁?yè)的數(shù)據(jù)依賴于上一頁(yè)最后一條數(shù)據(jù),所以無(wú)法跳頁(yè)請(qǐng)求(但可以通過(guò)循環(huán)來(lái)實(shí)現(xiàn)),且返回的始終是最新的數(shù)據(jù),在分頁(yè)過(guò)程中數(shù)據(jù)的位置可能會(huì)有變更,這種分頁(yè)方式更加符合moa的業(yè)務(wù)場(chǎng)景,常用于數(shù)據(jù)導(dǎo)出等場(chǎng)景。


隨機(jī)內(nèi)容

表情

共0條評(píng)論
  • 這篇文章還沒(méi)有收到評(píng)論,趕緊來(lái)?yè)屔嘲l(fā)吧~