es数据写入、删除和更新

转载于: https://www.jianshu.com/p/d9e5451456e6

 

数据写入过程:


 
写入过程

注:一个数据不会写入多个主分片


 
底层逻辑

注:数据先写入Buffer,同时写入Translog(用于极端情况下的数据恢复),Buffer缓存数据达到阈值会批量刷到磁盘(中间有个文件系统缓冲),所以说es的数据写入是一个近实时的(存才延时默认是1秒)

单条写入put/post:

1、put,需要设定数据ID(同一条数据首次插入是created,再次插入会updated)
2、post,可选择设定数据ID(不指定id情况下:同一条数据首次插入是created,再次插入还是created,但_id会变;指定id若id不变第二次插入失败)
_doc:同一条数据首次插入是created,再次插入会updated
_create:同一条数据首次插入是created,再次插入会报错

PUT compyan-starff-001/_doc/1
{
  ...
}
PUT compyan-starff-001/_create/1
{
  ...
}

result,created/updated,新增或更新

req请求参数解读:

op_type,操作类型
refresh,刷新策略

PUT compyan-starff-001/_doc/1?routing=1 #路由到第一个主分片
{
  ...
}

routing,路由策略
Wait_for_active_shards,等待写入分片数量

GET company-staff-001/_doc/1  #通过这种方式可以立即获取到插入的数据,因为这种GET方式会直接
#从Buffer中回去数据(实时)
GET company-staff-001/_search?routing=1  #_search需要路由到指定的分段从磁盘中获取数据(这种是非实时)
#PUT数据时可以通过&refresh=true强制实时(也是近实时)

批量写入_bulk:

POST _bulk
{index:{"_index":"company-staff-001", "_id": "1"}}
...
{index:{"_index":"company-staff-001", "_id": "2"}}
...
{index:{"_index":"company-staff-001", "_id": "3"}}
...

数据删除:

删除的路由机制和写入的路由机制相同


 
删除内部机制
DELETE company-staff-001/_doc/1
#如插入数据时_version为1,删除是版本号为_version为2,原因:标记删除先更新了数据版本发生变化,默认情况编辑删除的数据能保存24小时

条件删除:_delete_by_query

POST kibana_sample_data_logs_delete/_delete_by_query?requests_per_second
{
  "slice":{   #手动分片删除
    "id":1,    #两次删除需要修改id
    "max":2 #分为两批次删除
  }
  "query": { 
    "match_all": {}
  }
}
POST kibana_sample_data_logs_delete/_delete_by_query?slice=2&scroll_size=1000&requests_per_second=100    
      #自动分片删除,最大的片数不能超过自己的分片数

requests_per_second:每秒删除多少条数据
注:一般需要加上requests_per_second来控制删除;若不加,在条件删除海量数据时,可能执行时间比较长,造成es瞬间io巨大,属于危险操作
scroll_size:每次从es遍历多少条数据存储到Buffer中
requests_per_second:每秒多少条

GET _cat/tasks  #查询所有任务
GET _tasks?detailed=true&actions=*/delete/byquery  #查询上面的删除任务

批量删除:

POST _bulk?refresh=true  #刷新
{"delete":{"_index":"company-staff-001", "_id":"1"}}
{"delete":{"_index":"company-staff-001", "_id":"2"}}
{"delete":{"_index":"company-staff-001", "_id":"3"}}

mysql数据库批量导入数据到es可以使用logstash,原理就是使用了"_bulk"命令

思考:批量输出数据,当数据量过大时,不如直接删除索引,再重新导入数据

更新

1、全量更新

#第二次put会全量更新
POST compyan-starff-001/_doc/1
{
  ...
}

2、局部更新

POST compyan-starff-001/_update/1
{
  "_doc":{
    "companyName":"xx公司"
  }
#重要:false当id为1的记录不存在时会更新报错,true当id为1的记录不存在时会创建索引并插入记录
"doc_as_upset":true
}

3、脚本更新

只更新记录中companyName字段内容
POST compyan-starff-001/_update/1?refresh=true
{
  "script":{
    "source":"""
    ctx._source. companyName="aaa公司";
    """,
    "lang":"painless",
    "params":{}
  }
}
或
POST compyan-starff-001/_update/1?refresh=true
{
  "script":{
    "source":"""
    ctx._source. companyName=params.cName;
    """,
    "lang":"painless",
    "params":{
    "cName":"aaa公司"
    }
  }
}
或
POST compyan-starff-001/_update/1?refresh=true
{
  "upsert":{
    "companyName"="aaa公司"
    }
}

批量更新_bulk:

POST _bulk?refresh=true
{"upadte":{"_index":"compyan-starff-001","_id":"1"}}
{"_doc":{"compaynId":"2020","userId":"1234"}}
{"upadte":{"_index":"compyan-starff-001","_id":"2"}}
{"_doc":{"compaynId":"2021","userId":"12345"}}
{"upadte":{"_index":"compyan-starff-001","_id":"3"}}
{"_doc":{"compaynId":"2022","userId":"123456"}}

"result":"noop"表示跟进前后数据相同,es没有做操作,(es会先做检查)
"_version"当更新不成功时,版本号依然会加1,若要指定版本号,可以外部设置,但是版本号必须必目前版本号大,否则报错

条件更新:

"_update_by_query"和条件删除类似



作者:奋斗的韭菜汪
链接:https://www.jianshu.com/p/d9e5451456e6
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

posted @ 2021-11-04 14:52  小猪冒泡  阅读(6378)  评论(0编辑  收藏  举报