zoukankan      html  css  js  c++  java
  • 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. 索引(插入)或查询性能是否占主导地位取决于诸多因素,比如:重新索引文档和集群进行重新索引。

     

     

  • 相关阅读:
    数据结构-包含min函数的栈
    数据结构-顺时针打印矩阵
    数据结构-二叉树的镜像
    数据结构-树的子结构
    数据结构-合并两个排序的链表
    数据结构-反转链表
    数据结构-链表中倒数第K个节点
    数据结构-调整数组顺序使奇数位于偶数前面
    数据结构-在O(1)时间删除链表节点
    数据结构-打印1到最大的n位数
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11864057.html
Copyright © 2011-2022 走看看