• elasticsearch 基础 —— Delete By Query API


    Delete By Query API

    _delete_by_query 的简单用法,就是在查询匹配到的每个文档上执行删除。例如:

    POST twitter/_delete_by_query
    {
      "query": { ①
        "match": {
          "message": "some message"
        }
      }
    }

    ①:查询必须是有效的键值对,query是键,这和Search API是同样的方式。在search apiq参数和上面效果是一样的。

    返回如下内容:

    {
      "took" : 147,
      "timed_out": false,
      "deleted": 119,
      "batches": 1,
      "version_conflicts": 0,
      "noops": 0,
      "retries": {
        "bulk": 0,
        "search": 0
      },
      "throttled_millis": 0,
      "requests_per_second": -1.0,
      "throttled_until_millis": 0,
      "total": 119,
      "failures" : [ ]
    }

     _delete_by_query在索引启动时获取索引的快照,并使用internal版本控制删除它找到的内容。这意味着如果文档在拍摄快照的时间和处理删除请求之间发生更改,则会出现版本冲突。当版本匹配时,文档将被删除。

    由于internal版本控制不支持将值0作为有效版本号,因此无法使用版本等于0的文档删除, _delete_by_query并且将使请求失败。

    _delete_by_query执行期间,顺序执行多个搜索请求以便找到要删除的所有匹配文档。每次找到一批文档时,都会执行相应的批量请求以删除所有这些文档。如果搜索或批量请求被拒绝,则_delete_by_query依赖于默认策略来重试被拒绝的请求(最多10次,指数后退)。达到最大重试次数限制会导致_delete_by_query 中止,并failures在响应中返回所有失败。已执行的删除仍然有效。换句话说,该过程不会回滚,只会中止。当第一个失败导致中止时,失败的批量请求返回的所有失败都将返回到failures元件; 因此,可能存在相当多的失败实体。

    如果您想计算版本冲突而不是让它们中止,那么请conflicts=proceed在URL或"conflicts": "proceed"请求正文中设置。

    下面仅仅只是删除索引twitter中类型tweet的所有数据:

    POST twitter/tweet/_delete_by_query?conflicts=proceed
    {
      "query": {
        "match_all": {}
      }
    }

    一次删除多个索引中的多个类型中的数据,也是可以的。例如:

    POST twitter,blog/tweet,post/_delete_by_query
    {
      "query": {
        "match_all": {}
      }
    }

    如果你提供了routing,接着这个路由会被复制给scroll query,根据匹配到的路由值,来决定哪个分片来处理:

    POST twitter/_delete_by_query?routing=1
    {
      "query": {
        "range" : {
            "age" : {
               "gte" : 10
            }
        }
      }
    }

    默认情况下,_delete_by_query自上而下批量1000条数据,你也可以在URL中使用参数scroll_size

    POST twitter/_delete_by_query?scroll_size=5000
    {
      "query": {
        "term": {
          "user": "kimchy"
        }
      }
    }

    URL参数

    除了标准的参数,如pretty,删除通过查询API也支持refreshwait_for_completionwait_for_active_shardstimeout 和scroll

    发送refresh请求将在请求完成后刷新查询删除中涉及的所有分片。这与Delete API的refresh 参数不同,后者仅导致接收删除请求的分片被刷新。

    如果请求包含,wait_for_completion=false则Elasticsearch将执行一些预检检查,启动请求,然后返回task 可与Tasks API 一起使用以取消或获取任务状态的请求。Elasticsearch还将创建此任务的记录作为文档.tasks/task/${taskId}。这是你的保留或删除你认为合适。完成后,删除它,以便Elasticsearch可以回收它使用的空间。

    wait_for_active_shards控制在继续请求之前必须激活碎片的副本数量。详情请见此处 。timeout控制每个写入请求等待不可用分片变为可用的时间。两者都完全适用于 Bulk API中的工作方式。由于_delete_by_query采用滚动搜索,你还可以指定scroll参数来控制多长时间保持“搜索上下文”活着,例如?scroll=10m,默认情况下它是5分钟。

    requests_per_second可以被设置为任何正十进制数(1.46, 1000等)和节流速率_delete_by_query通过填充每个批次由一等待时间发出的删除操作的批次。可以通过设置requests_per_second为禁用限制-1

    通过在批处理之间等待来完成限制,以便在_delete_by_query内部使用的滚动 可以被赋予考虑填充的超时。填充时间是批量大小除以requests_per_second写入所花费的时间之间的差异。默认情况下,批处理大小为1000,因此如果requests_per_second设置为500

    target_time = 1000 / 500 per second = 2 seconds
    wait_time = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds

    由于批处理是作为单个_bulk请求发出的,因此大批量数据将导致Elasticsearch创建许多请求,然后等待一段时间再开始下一组。这是“突发”而不是“平滑”。默认是-1

    Response body

    {
      "took" : 147,
      "timed_out": false,
      "total": 119,
      "deleted": 119,
      "batches": 1,
      "version_conflicts": 0,
      "noops": 0,
      "retries": {
        "bulk": 0,
        "search": 0
      },
      "throttled_millis": 0,
      "requests_per_second": -1.0,
      "throttled_until_millis": 0,
      "failures" : [ ]
    }

    took

    整个操作从开始到结束的毫秒数。

    timed_out

    true如果在通过查询执行删除期间执行的任何请求超时 ,则将此标志设置为。

    total

    已成功处理的文档数。

    deleted

    已成功删除的文档数。

    batches

    通过查询删除拉回的滚动响应数。

    version_conflicts

    按查询删除的版本冲突数。

    noops

    对于按查询删除,此字段始终等于零。它只存在,以便通过查询删除,按查询更新和reindex API返回具有相同结构的响应。

    retries

    通过查询删除尝试的重试次数。bulk是重试的批量操作search的数量,是重试的搜索操作的数量。

    throttled_millis

    请求睡眠符合的毫秒数requests_per_second

    requests_per_second

    在通过查询删除期间有效执行的每秒请求数。

    throttled_until_millis

    在按查询响应删除时,此字段应始终等于零。它只在使用Task API时有意义,它指示下一次(自纪元以来的毫秒数),为了符合,将再次执行受限制的请求requests_per_second

    failures

    如果在此过程中存在任何不可恢复的错误,则会出现故障数组。如果这是非空的,那么请求因为那些失败而中止。逐个查询是使用批处理实现的,任何故障都会导致整个进程中止,但当前批处理中的所有故障都会被收集到数组中。您可以使用该conflicts选项来防止reindex在版本冲突中中止。

    Works with the Task API

    你可以使用Task API来获取任何一个正在运行的delete-by-query请求的状态。

    GET _tasks?detailed=true&actions=*/delete/byquery
    

    返回如下内容:

    {
      "nodes" : {
        "r1A2WoRbTwKZ516z6NEs5A" : {
          "name" : "r1A2WoR",
          "transport_address" : "127.0.0.1:9300",
          "host" : "127.0.0.1",
          "ip" : "127.0.0.1:9300",
          "attributes" : {
            "testattr" : "test",
            "portsfile" : "true"
          },
          "tasks" : {
            "r1A2WoRbTwKZ516z6NEs5A:36619" : {
              "node" : "r1A2WoRbTwKZ516z6NEs5A",
              "id" : 36619,
              "type" : "transport",
              "action" : "indices:data/write/delete/byquery",
              "status" : {    ①
                "total" : 6154,
                "updated" : 0,
                "created" : 0,
                "deleted" : 3500,
                "batches" : 36,
                "version_conflicts" : 0,
                "noops" : 0,
                "retries": 0,
                "throttled_millis": 0
              },
              "description" : ""
            }
          }
        }
      }
    }

    ①这个对象包含实际的状态。响应体是json格式,其中total字段是非常重要的。total表示期望执行reindex操作的数量。你可以通过加入的updatedcreateddeleted字段来预估进度。但它们之和等于total字段时,请求将结束。

    使用task id可以直接查找此task

    GET /_tasks/taskId:1

    这个api的优点是它整合了wait_for_completion=false来透明的返回已完成任务的状态。如果此任务完成并且设置为wait_for_completion=false,那么其将返回results或者error字段。这个特性的代价就是当设置wait_for_completion=false时,会在.tasks/task/${taskId}中创建一个文档。当然你也可以删除这个文档。

    Works with the Cancel Task API

    任何一个Delete By Query都可以使用Task Cancel API来取消掉:

    POST _tasks/task_id:1/_cancel

    可以使用上面的task api来找到task_id; 
    取消应该尽快发生,但是也可能需要几秒钟,上面的task 状态 api将会进行列出task直到它被唤醒并取消自己。

    Rethrottling

    requests_per_second的值可以在使用_rethrottle参数的正在运行的delete by queryapi上进行更改:

    POST _delete_by_query/task_id:1/_rethrottle?requests_per_second=-1

    使用上面的tasks API来查找task_id

    就像在_delete_by_query中设置一样,requests_per_second可以设置-1来禁止这种限制或者任何一个10进制数字,像1.7或者12来限制到这种级别。加速查询的Rethrottling会立即生效,但是缓慢查询的Rethrottling将会在完成当前批处理后生效。这是为了防止scroll timeouts

    Manually slicing

    Delete-by-query支持Sliced Scroll,其可以使你相对容易的手动并行化进程:

    POST twitter/_delete_by_query
    {
      "slice": {
        "id": 0,
        "max": 2
      },
      "query": {
        "range": {
          "likes": {
            "lt": 10
          }
        }
      }
    }
    POST twitter/_delete_by_query
    {
      "slice": {
        "id": 1,
        "max": 2
      },
      "query": {
        "range": {
          "likes": {
            "lt": 10
          }
        }
      }
    }

    你可以通过以下方式进行验证:

    GET _refresh
    POST twitter/_search?size=0&filter_path=hits.total
    {
      "query": {
        "range": {
          "likes": {
            "lt": 10
          }
        }
      }
    }

    像下面这样只有一个total是合理的:

    {
      "hits": {
        "total": 0
      }
    }

    Automatic slicing

    你也可以使用Sliced Scrolldelete-by-query api自动并行化,以在_uid上切片:

    POST twitter/_delete_by_query?refresh&slices=5
    {
      "query": {
        "range": {
          "likes": {
            "lt": 10
          }
        }
      }
    }

    你可以通过以下来验证:

    POST twitter/_search?size=0&filter_path=hits.total
    {
      "query": {
        "range": {
          "likes": {
            "lt": 10
          }
        }
      }
    }

    像下面的total是一个合理的结果:

    {
      "hits": {
        "total": 0
      }
    }

    添加slices_delete_by_query将会自动执行上面部分中使用手动处理的部分,创建子请求这意味着有些怪事:

    1. 你可以在Tasks APIs中看到这些请求。这些子请求是使用了slices请求任务的子任务。
    2. 为此请求(使用了slices)获取任务状态仅仅包含已完成切片的状态。
    3. 这些子请求都是独立寻址的,例如:取消和rethrottling.
    4. Rethrottling the request with slices will rethrottle the unfinished sub-request proportionally.
    5. 取消slices请求将会取消每个子请求。
    6. 由于slices的性质,每个子请求并不会得到完全均匀的文档结果。所有的文档都将要处理,但是有些slices(切片)会大些,有些会小些。希望大的slices(切片)有更均匀的分配。
    7. slices请求中像requests_per_secondsize参数,按比例分配给每个子请求。结合上面的关于分配的不均匀性,你应该得出结论:在包含slices_delete_by_query请求中使用size参数可能不会得到正确大小的文档结果。
    8. 每个子请求都会获得一个略微不同的源索引快照,尽管这些请求都是大致相同的时间。

    Picking the number of slices

    这里我们有些关于slices数量的建议(如果是手动并行的话,那么在slice api就是max参数):

    1. 不要使用大数字。比如500,将会创建相当大规模的CPU震荡。 
      这里说明下震荡(thrashing)的意思: 
      cpu大部分时间都在进行换页,而真正工作时间却很短的现象称之为thrashing (震荡)
    2. 从查询性能角度来看,在源索引中使用多个分片是更高效的。
    3. 从查询性能角度来看,在源索引中使用和分片相同的数量是更高效的。
    4. 索引性能应该在可利用slices之间进行线性扩展。
    5. 索引(插入)或查询性能是否占主导地位取决于诸多因素,比如:重新索引文档和集群进行重新索引。

     

     

  • 相关阅读:
    我的浏览器收藏夹分类
    我的浏览器收藏夹分类
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11864057.html
Copyright © 2020-2023  润新知