3.Elasticsearch学习之深度分页、游标查询、以及批量操作

1.深度分页

1.分页查询

POST /shop/_doc/_search 

{ 
  "query": { 
  	"match_all": {} 
  },
  "from": 0, 
  "size": 10 
}

2.深度分页

深度分页其实就是搜索的深浅度,比如第1页,第2页,第10页,第20页,是比较浅的;第10000页,第20000页就是很深了。

使用如下操作:

{ 
  "query": { 
      "match_all": {} 
  },
  "from": 9990, 
  "size": 10 
}



{ 
  "query": { 
  		"match_all": {} 
  },
  "from": 9999, 
  "size": 10 
}

我们在获取第9999条到10009条数据的时候,其实每个分片都会拿到10009条数据,然后集合在一起,总共是10009*3=30027条数据,针对30027数据再次做排序

会获取最后10条数据。

如此一来,搜索得太深,就会造成性能问题,会耗费内存和占用cpu。而且es为了性能,他不支持超过一万条数据以上的分页查询。那么如何解决深度分页带来的

实我们应该避免深度分页操作(限制分页页数),比如最多只能提供100页的展示,从第101页开始就没了,毕竟用户也不会搜的那么深,我们平时搜索淘宝或者

也就看个10来页就顶多了。

譬如淘宝搜索限制分页最多100页,如下:

3.Elasticsearch学习之深度分页、游标查询、以及批量操作_第1张图片

2.深度分页 - 提升搜索量

提升搜索量

“changing the [index.max_result_window] index level setting”

通过设置index.max_result_window来突破10000数据

GET /shop/_settings 

PUT /shop/_settings 
{ 
    "index.max_result_window": "20000" 
}

3.scroll api 游标查询/滚动搜索

一次性查询1万+数据,往往会造成性能影响,因为数据量太多了。这个时候可以使用滚动搜索,也就是 scroll 。

滚动搜索可以先查询出一些数据,然后再紧接着依次往下查询。在第一次查询的时候会有一个滚动id,相当于一个 锚标记 ,随后再次滚动搜索会需要上一次搜索,根据这个进行下一次的搜索请求。每次搜索都是基于一个历史的数据快照,查询数据的期间,如果有数据变更,那么和搜索是没有关系的,搜索的内容还是上一次快照。

游标查询会取某个时间点的快照数据。 查询初始化之后索引上的任何变化会被它忽略。

  • scroll=1m,相当于是一个session会话时间,搜索保持的上下文时间为1分钟。
POST /shop/_search?scroll=1m 

{ 
  "query": { 
    "match_all": { 
    } 
  },
  "sort" : ["_doc"], 
  "size": 5 
}

//拷贝_scroll_id的值 ,每次请求都要更换_scroll_id

POST /_search/scroll 
{
  "scroll": "1m", 
  "scroll_id" : "your last scroll_id" 
}

官文地址:https://www.elastic.co/guide/cn/elasticsearch/guide/current/scroll.html

这个查询的返回结果包括一个字段 _scroll_id, 它是一个base64编码的长字符串。

注意:注意游标查询每次返回一个新字段 _scroll_id。每次我们做下一次游标查询, 我们必须把前一次查询返回的字段 _scroll_id 传递进去。 当没有更多的结果返回的时候,我们就处理完所有匹配的文档了。

4.批量查询

之前的批量搜索查询:

Get http://123.57.129.206:9200/shop/_doc/_search

{
    "query":{
        "ids":{
            "type":"_doc",
            "values":["1001","1003","1004"]
        }
    }
}

现在的批量查询方式:

Get http://123.57.129.206:9200/shop/_doc/_mget

{
    "ids":["1001","1002","10018"]
}

注意:查询的结果如果不存在,也会检索出来,不过这个显示的是"found": false

两种方式的查询各有不同,search查询的信息更多更全,但是_mget的使用更方便_

5.批量操作 bulk

基本语法

bulk操作和以往的普通请求格式有区别。不要格式化json,不然就不在同一行了,这个需要注意。

{ action: { metadata }}\n 
{ request body }\n 
{ action: { metadata }}\n 
{ request body }\n 

... 
  • { action: { metadata }} 代表批量操作的类型,可以是新增、删除或修改

  • \n 是每行结尾必须填写的一个规范,每一行包括最后一行都要写,用于es的解析

  • { request body } 是请求body,增加和修改操作需要,删除操作则不需要

批量操作的类型

action 必须是以下选项之一:

  • create:如果文档不存在,那么就创建它。存在会报错。发生异常报错不会影响其他操作。

  • index:创建一个新文档或者替换一个现有的文档。

  • update:部分更新一个文档。

  • delete:删除一个文档。

metadata 中需要指定要操作的文档的 _index 、 _type 和 _id , _index 、 _type 也可以在url中指定

实操

  • create新增文档数据,在metadata中指定index以及type
POST /_bulk 
//类型
{"create": {"_index": "shop2", "_type": "_doc", "_id": "2001"}} 
//数据
{"id": "2001", "nickname": "name2001"} 

{"create": {"_index": "shop2", "_type": "_doc", "_id": "2002"}} 
{"id": "2002", "nickname": "name2002"} 
{"create": {"_index": "shop2", "_type": "_doc", "_id": "2003"}} 
{"id": "2003", "nickname": "name2003"}
  • create创建已有id文档,在url中指定index和type
POST /shop/_doc/_bulk 

{"create": {"_id": "2003"}} 
{"id": "2003", "nickname": "name2003"} 
{"create": {"_id": "2004"}} 
{"id": "2004", "nickname": "name2004"} 
{"create": {"_id": "2005"}} 
{"id": "2005", "nickname": "name2005"}
  • index创建,已有文档id会被覆盖,不存在的id则新增
POST /shop/_doc/_bulk 

{"index": {"_id": "2004"}} 
{"id": "2004", "nickname": "index2004"} 
{"index": {"_id": "2007"}} 
{"id": "2007", "nickname": "name2007"} 
{"index": {"_id": "2008"}} 
{"id": "2008", "nickname": "name2008"}
  • update部分修改,对已有数据进行更改
POST /shop/_doc/_bulk

{"update":{"_id":"2002"}}
{"doc":{"id": 2222}}
{"update":{"_id":"2003"}}
{"doc":{"nickname": "name2333"}}
  • delete删除操作,注意删除操作用的post请求
post /shop/_doc/_bulk

{"delete":{"_id":"2002"}}

{"delete":{"_id":"2003"}}

也可以一起使用:删除、新增和修改一起使用,举例如下:

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} 
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "My first blog post" }
{ "index":  { "_index": "website", "_type": "blog" }}
{ "title":    "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} } 

注意:批量操作过程中,其中一个数据操作报错,并不会影响其他的数据操作。

详细可参考官方文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/bulk.html

多大是太大了?

​ 整个批量请求都需要由接收到请求的节点加载到内存中,因此该请求越大,其他请求所能获得的内存就越少。 批量请求的大小有一个最佳值,大于这个值,性能将不再提升,甚至会下降。 但是最佳值不是一个固定的值。它完全取决于硬件、文档的大小和复杂度、索引和搜索的负载的整体情况。

​ 幸运的是,很容易找到这个 最佳点 :通过批量索引典型文档,并不断增加批量大小进行尝试。 当性能开始下降,那么你的批量大小就太大了。一个好的办法是开始时将 1,000 到 5,000 个文档作为一个批次, 如果你的文档非常大,那么就减少批量的文档个数。

​ 密切关注你的批量请求的物理大小往往非常有用,一千个 1KB 的文档是完全不同于一千个 1MB 文档所占的物理大小。 一个好的批量大小在开始处理后所占用的物理大小约为 5-15 MB。

你可能感兴趣的:(elasticsearch,elasticsearch)