--- title: "强制合并索引" date: 2026-03-01 lastmod: 2026-03-01 description: "强制合并索引的段文件,减少段数量并释放存储空间" tags: ["索引管理", "索引优化", "性能优化"] summary: "强制合并索引的段文件,减少段数量,提高查询性能并释放存储空间。 API # POST /_forcemerge POST /{index}/_forcemerge API 的作用 # 该 API 用于强制合并索引的段文件(segments),主要作用包括: 减少段数量:将多个小段合并为较少的大段 提高查询性能:减少需要搜索的段数量 释放存储空间:清除已删除的文档 优化索引结构:减少磁盘 I/O 什么是段合并? # Easysearch 使用段(segments)来存储索引数据。新文档会被添加到新段中,随着时间推移,段数量会增加。段合并操作将多个段合并为更大的段,提高查询效率。 使用场景 # 索引完成后优化查询性能 清理大量已删除文档 减少段数量以节省内存 定期维护只读索引 警告:Force Merge 是一个资源密集型操作,可能会影响集群性能。建议在低峰期执行。 API 的参数 # 路由参数 # 参数 类型 是否必填 描述 {index} 字符串 否 要合并的索引名称。支持:单个索引、逗号分隔的多个索引、通配符表达式。不指定则操作所有索引 Query String 参数 # 参数 类型 是否必填 默认值 描述 max_num_segments 整数 否 -1 目标段数量。设置为 1 将合并为单个段 only_expunge_deletes 布尔值 否 false 是否只清理已删除文档,不合并未删除的文档 flush 布尔值 否 true 是否在合并后执行刷新操作 参数说明 # max_num_segments # 强制将索引合并到指定的段数量或更少 设置为 1 会将整个索引合并为单个段(最大程度优化) 默认值 -1 表示使用默认合并策略 值越小,合并时间越长,消耗资源越多 only_expunge_deletes # true:只合并含有大量删除的段 false:执行完整的段合并(默认) 与 max_num_segments 同时使用时会产生警告 flush # true:合并后执行刷新,使更改可见 false:不刷新,稍后手动刷新 示例 # 合并所有索引为单个段 # POST /_forcemerge?" --- 强制合并索引的段文件,减少段数量,提高查询性能并释放存储空间。 ## API ``` POST /_forcemerge POST /{index}/_forcemerge ``` ## API 的作用 该 API 用于强制合并索引的段文件(segments),主要作用包括: - **减少段数量**:将多个小段合并为较少的大段 - **提高查询性能**:减少需要搜索的段数量 - **释放存储空间**:清除已删除的文档 - **优化索引结构**:减少磁盘 I/O ### 什么是段合并? Easysearch 使用段(segments)来存储索引数据。新文档会被添加到新段中,随着时间推移,段数量会增加。段合并操作将多个段合并为更大的段,提高查询效率。 ### 使用场景 - 索引完成后优化查询性能 - 清理大量已删除文档 - 减少段数量以节省内存 - 定期维护只读索引 > **警告**:Force Merge 是一个资源密集型操作,可能会影响集群性能。建议在低峰期执行。 ## API 的参数 ### 路由参数 | 参数 | 类型 | 是否必填 | 描述 | |------|------|----------|------| | `{index}` | 字符串 | 否 | 要合并的索引名称。支持:单个索引、逗号分隔的多个索引、通配符表达式。不指定则操作所有索引 | ### Query String 参数 | 参数 | 类型 | 是否必填 | 默认值 | 描述 | |------|------|----------|--------|------| | `max_num_segments` | 整数 | 否 | -1 | 目标段数量。设置为 1 将合并为单个段 | | `only_expunge_deletes` | 布尔值 | 否 | false | 是否只清理已删除文档,不合并未删除的文档 | | `flush` | 布尔值 | 否 | true | 是否在合并后执行刷新操作 | ### 参数说明 #### max_num_segments - 强制将索引合并到指定的段数量或更少 - 设置为 1 会将整个索引合并为单个段(最大程度优化) - 默认值 -1 表示使用默认合并策略 - 值越小,合并时间越长,消耗资源越多 #### only_expunge_deletes - `true`:只合并含有大量删除的段 - `false`:执行完整的段合并(默认) - 与 `max_num_segments` 同时使用时会产生警告 #### flush - `true`:合并后执行刷新,使更改可见 - `false`:不刷新,稍后手动刷新 ## 示例 ### 合并所有索引为单个段 ```bash POST /_forcemerge?max_num_segments=1 ``` **响应示例:** ```json { "_shards": { "total": 10, "successful": 10, "failed": 0 } } ``` ### 合并特定索引 ```bash POST /my_index/_forcemerge?max_num_segments=1 ``` ### 合并多个索引 ```bash POST /index1,index2/_forcemerge?max_num_segments=3 ``` ### 只清理已删除文档 ```bash POST /my_index/_forcemerge?only_expunge_deletes=true ``` ### 合并后不刷新 ```bash POST /my_index/_forcemerge?max_num_segments=1&flush=false ``` ### 使用通配符合并索引 ```bash POST /logs-2025-*/_forcemerge?max_num_segments=1 ``` ## 响应字段说明 | 字段 | 类型 | 描述 | |------|------|------| | `_shards.total` | 整数 | 总分片数 | | `_shards.successful` | 整数 | 成功的分片数 | | `_shards.failed` | 整数 | 失败的分片数 | ## 使用场景 ### 场景 1:优化只读索引 对于不再写入的索引,可以合并为单个段以获得最佳查询性能: ```bash # 合并历史日志索引 POST /logs-2024-*/_forcemerge?max_num_segments=1 ``` ### 场景 2:清理已删除文档 大量删除文档后,清理空间: ```bash POST /my_index/_forcemerge?only_expunge_deletes=true ``` ### 场景 3:时间序列索引优化 ```bash # 每日优化昨天的索引 POST /logs-$(date -d 'yesterday' +%Y.%m.%d)/_forcemerge?max_num_segments=1 ``` ## 性能考虑 ### 资源消耗 | 资源 | 影响 | |------|------| | CPU | 高 - 需要大量计算进行合并 | | 磁盘 I/O | 高 - 需要读写大量数据 | | 磁盘空间 | 需要额外空间 - 合并过程中需要临时空间 | | 内存 | 中等 - 需要缓冲区进行合并 | ### 最佳实践 1. **低峰期执行**:在业务低峰期执行,避免影响正常服务 2. **分批执行**:对于大量索引,分批执行而非一次性合并所有索引 3. **监控磁盘空间**:确保有足够的磁盘空间用于合并过程 4. **只读索引**:只对不再写入的索引执行强制合并 5. **避免频繁执行**:频繁执行会增加不必要的开销 ### 合并建议 | 索引类型 | max_num_segments 建议 | |----------|----------------------| | 活跃写入索引 | 不建议执行 | | 偶尔写入索引 | 2-5 个段 | | 只读索引 | 1 个段 | ## 注意事项 1. **不可逆操作**:合并后的段无法拆分 2. **磁盘空间**:合并过程中需要临时磁盘空间 3. **时间索引**:对于基于时间的索引(如日志),只对旧索引执行 4. **复制索引**:合并副本会自动同步到副本分片 5. **写入影响**:合并期间索引仍可读写,但性能会下降 ## Force Merge vs 自动合并 | 特性 | Force Merge | 自动合并 | |------|-------------|----------| | 触发方式 | 手动 API | 自动后台进程 | | 合并程度 | 可控(指定段数) | 基于策略 | | 资源消耗 | 高 | 中等 | | 执行时间 | 立即执行 | 后台渐进 | | 使用场景 | 优化只读索引 | 日常维护 |