码迷,mamicode.com
首页 > 其他好文 > 详细

更有效的批处理(cheaper in bulk)

时间:2014-05-17 19:24:37      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:blog   class   c   ext   http   int   

mget允许我们一次检索多个document,而bulk API则允许我们在一个请求中做create,index,update 或者delete。如果你要index一个数据流如日志数据,bulk是很实用的,bulk可以能排队数百或数千的批次处理。

bulk的请求体有点不同寻常,如下:

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

这个格式好像一行一行的用“\n”换行符分割的JSON document的集合。有两个要点需要注意:

1:每一行都要使用换行符“\n"分割,包括最后一行。这些换行符用来标记分割。

2:每一行都不能包括非转义的换行符,因为这些非法符号会影响JSON的解析

 

Why the funny format? 中将会解释为什么bulk API要使用这种格式。

上面action/metadata这一行指定了将要对那个document做什么操作。

action必须是index,create,update,delete中的一个,metadata应该指定要操作的document的_index,_type和_id。

例如,一个删除的请求应该是这样的:

{"delete":{"_index":"website","_type":"blog","_id":"123"}}

请求体这行包含了document的_source自身——也就是document包含的字段以及字段值,这个对index和create操作是必要的,这也是必须注意的是:你一定要提供index的document。这对update操作也是必须的,并且也要包括你要update的请求体如doc,upsert,script等。不许要请求体的是delete动作。

{"create":  {"_index":"website","_type":"blog","_id":"123"}}
{"title":    "My first blog post"}

 如果没有指定一个_id,那么ES就会自动生成一个:

{"index":{"_index":"website","_type":"blog"}}
{"title":    "My second blog post"}

 几个操作放在一起,一个完整的bulk请求就如一下示例:

POST /_bulk
{"delete":{"_index":"website","_type":"blog","_id":"123"}}bubuko.com,布布扣
{"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"}}bubuko.com,布布扣

标记1表示了一个delete动作是不许要请求体的,后面可以直接跟随其他的动作

标记2表示这里应该是一个换行符

相应消息体包括了items数组,这个数组列出了每个请求的操作结果,次序是和请求是保持一致的:

{
   
"took":4,
   
"errors":false,bubuko.com,布布扣
   
"items":[
     
{  "delete":{
           
"_index":   "website",
           
"_type":    "blog",
           
"_id":      "123",
           
"_version":2,
           
"status":   200,
           
"found":    true
     
}},
     
{  "create":{
           
"_index":   "website",
           
"_type":    "blog",
           
"_id":      "123",
           
"_version":3,
           
"status":   201
     
}},
     
{  "create":{
           
"_index":   "website",
           
"_type":    "blog",
           
"_id":      "EiwfApScQiiy7TIKFxRCTw",
           
"_version":1,
           
"status":   201
     
}},
     
{  "update":{
           
"_index":   "website",
           
"_type":    "blog",
           
"_id":      "123",
           
"_version":4,
           
"status":   200
     
}}
   
]
}}

标记1表示所有的请求操作都是成功的。

每个子请求都是独立执行的,一个执行失败并不能影响其他操作的执行。如果有任何一个操作失败,响应体中的顶级error的值就是true,详细的错误信息就会在相应的响应体作出答复:

POST /_bulk
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":    "Cannot create - it already exists"}
{"index":  {"_index":"website","_type":"blog","_id":"123"}}
{"title":    "But we can update it"}

在上面这个执行响应体中,我们能看到create一个id是123的document是失败的,因为这个document已经存在了,但是其后的index请求是成功的:

{
   
"took":3,
   
"errors":true,bubuko.com,布布扣
   
"items":[
     
{  "create":{
           
"_index":   "website",
           
"_type":    "blog",
           
"_id":      "123",
           
"status":   409,bubuko.com,布布扣
           
"error":    "DocumentAlreadyExistsExceptionbubuko.com,布布扣
                       
[[website][4][blog][123]:
                        document already exists
]"
     
}},
     
{  "index":{
           
"_index":   "website",
           
"_type":    "blog",
           
"_id":      "123",
           
"_version":5,
           
"status":   200bubuko.com,布布扣
     
}}
   
]
}

标记1表示有一个或多个请求是失败的

标记2表示数据是冲突的,因为HTTP的状态码是409

标记3表示失败的详细细节

标记4表示这个操作是成功的

这也说明了bulk的请求不是原子性的——他们不能被用来实现记录。每一个请求都是独立的,所以一个请求的成功或者失败并不会影响到其他的请求操作。

 

不要重复自己

也许你要批量对logging数据插入到相同的index,并且type也是相同的,为每个document都指定相同的元数据是很糟糕的。就像mget API,bulk在URL请求中接受默认的/_index或者/_index/_type:

POST /website/_bulk
{"index":{"_type":"log"}}
{"event":"User logged in"}

你也能在metadata这一行重写URL中的_index,和_type:

POST /website/log/_bulk
{"index":{}}
{"event":"User logged in"}
{"index":{"_type":"blog"}}
{"title":"Overriding the default type"}

 

多大才是大

批处理请求通过接受请求的node把整个bulk加载到内存中,所以这个请求越大,为其他的请求剩余的内存空间就越小,有一个最佳的bulk请求大小,超个这个大小,性能不再提高,并且有可能会崩溃。

这个最佳的大小,并不是一个固定的数值,是依赖你的硬件换进,你的document的大小和复杂度,你的索引和搜索负荷。幸好,这个数值是容易找到的:

逐渐增加对典型的document的批处理数量,当着个性能开始降低的时候,你的批处理数量就是太大了。一个好的批处理数量值就是从1000到5000个document,如果你的document太大,这个数量就要减小。

注意bulk请求的物理数量是很有用的,一千个1KB的document和一千个1MB的数据是大有区别的,一个好的批处理数据量就是5-15M。

 

原文:http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/bulk.html

更有效的批处理(cheaper in bulk),布布扣,bubuko.com

更有效的批处理(cheaper in bulk)

标签:blog   class   c   ext   http   int   

原文地址:http://www.cnblogs.com/blog1350995917/p/3732901.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!