测试中的Elasticsearch的盘快满了,根据沟通后,只能是我手动删除,但是我又不想写代码,所以我就盯上了Elasticsearch中的API,用Delete By Query
的方式进行删除。
例如:要在Elasticsearch中根据create_time
字段删除三天以前的数据
方法1:
使用Delete By Query:
POST /your_index/_delete_by_query
{
"query": {
"range": {
"create_time": {
"lt": "now-3d/d",
"format": "strict_date_optional_time"
}
}
}
}
方法2:如果create_time是时间戳格式
POST /your_index/_delete_by_query
{
"query": {
"range": {
"create_time": {
"lt": "now-3d"
}
}
}
}
方法3:使用具体日期时间
POST /your_index/_delete_by_query
{
"query": {
"range": {
"create_time": {
"lt": "2023-11-01T00:00:00" // 替换为三天前的具体日期
}
}
}
}
但是我现在每个索引的数量比较大,所以在调用删除接口时应该加上"scroll_size": 1000
参数控制每次删除的文档数量,且需要添加"conflicts": "proceed"
参数以避免版本冲突报错。
方法4:滚动查询删除
POST /your_index/_delete_by_query?conflicts=proceed&scroll_size=5000
{
"query": {
"range": {
"create_time": {
"lt": "now-3d/d"
}
}
}
}
然后遇到的问题是执行完成后,就一直在等待了,索引数据量少的情况下等待时间比较少,但是数据量大的情况下,等待的时间就相对较长了,所以需要创建一个后台任务,我可以通过任务ID查询任务的执行情况,所以接口需要添加wait_for_completion=false
,返回一个任务ID。
最终方法:
POST /your_index/_delete_by_query?scroll_size=1000&conflicts=proceed&wait_for_completion=false
{
"query": {
"range": {
"create_time": {
"lt": "now-3d/d"
}
}
}
}
返回参数:
{ -
"task": "YtLbrYPaTWyh1eVVEAz4eQ:126303"
}
检查任务状态:
GET /_tasks/<task_id>
后续补充
执行完成后,索引空间并没有第一时间进行释放?
主要原因:
标记删除而非物理删除:
-
Elasticsearch 采用”标记删除”机制,只是将文档标记为”已删除”
-
实际数据仍在磁盘上,直到段(segment)合并时才会真正清除
段合并(Segment Merge)机制:
-
Elasticsearch 的 Lucene 底层采用不可变段结构
-
已删除文档只有在段合并过程中才会被物理移除
副本同步机制:
-
如果索引有副本,删除操作需要在所有副本上同步完成
解决办法:
手动触发段合并:
POST /your_index/_forcemerge?only_expunge_deletes=true&max_num_segments=1
参数说明:
-
only_expunge_deletes
:只合并包含删除文档的段 -
max_num_segments
:合并后的最大段数(设为1可获得最佳压缩)
⚠️ 注意:
-
强制合并是I/O密集型操作,避免在高负载时执行
-
大索引可能需要较长时间
-
合并过程中会暂时增加磁盘使用量
等待自动合并
Elasticsearch 默认会自动合并段,可通过设置调整策略:
PUT /your_index/_settings
{
"index.merge.policy.expunge_deletes_allowed": 10,
"index.merge.policy.deletes_pct_allowed": 20
}
暂无评论内容