Skip to content

Commit 4f11fa3

Browse files
committed
Add an index setting to control TieredMergePolicy#deletesPctAllowed (#32907)
This change adds an expert index setting called `index.merge.policy.deletes_pct_allowed`. It controls the maximum percentage of deleted documents that is tolerated in the index. Lower values make the index more space efficient at the expense of increased CPU and I/O activity. Values must be between `20` and `50`. Default value is `33`.
1 parent 5b60c61 commit 4f11fa3

File tree

7 files changed

+51
-6
lines changed

7 files changed

+51
-6
lines changed

server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
9696
IndexingSlowLog.INDEX_INDEXING_SLOWLOG_REFORMAT_SETTING,
9797
IndexingSlowLog.INDEX_INDEXING_SLOWLOG_MAX_SOURCE_CHARS_TO_LOG_SETTING,
9898
MergePolicyConfig.INDEX_COMPOUND_FORMAT_SETTING,
99+
MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING,
99100
MergePolicyConfig.INDEX_MERGE_POLICY_EXPUNGE_DELETES_ALLOWED_SETTING,
100101
MergePolicyConfig.INDEX_MERGE_POLICY_FLOOR_SEGMENT_SETTING,
101102
MergePolicyConfig.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE_SETTING,

server/src/main/java/org/elasticsearch/common/settings/Setting.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,11 +1303,18 @@ public static Setting<TimeValue> positiveTimeSetting(String key, TimeValue defau
13031303
}
13041304

13051305
public static Setting<Double> doubleSetting(String key, double defaultValue, double minValue, Property... properties) {
1306+
return doubleSetting(key, defaultValue, minValue, Double.POSITIVE_INFINITY, properties);
1307+
}
1308+
1309+
public static Setting<Double> doubleSetting(String key, double defaultValue, double minValue, double maxValue, Property... properties) {
13061310
return new Setting<>(key, (s) -> Double.toString(defaultValue), (s) -> {
13071311
final double d = Double.parseDouble(s);
13081312
if (d < minValue) {
13091313
throw new IllegalArgumentException("Failed to parse value [" + s + "] for setting [" + key + "] must be >= " + minValue);
13101314
}
1315+
if (d > maxValue) {
1316+
throw new IllegalArgumentException("Failed to parse value [" + s + "] for setting [" + key + "] must be <= " + maxValue);
1317+
}
13111318
return d;
13121319
}, properties);
13131320
}

server/src/main/java/org/elasticsearch/index/EsTieredMergePolicy.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,13 @@ public void setSegmentsPerTier(double segmentsPerTier) {
108108
public double getSegmentsPerTier() {
109109
return regularMergePolicy.getSegmentsPerTier();
110110
}
111+
112+
public void setDeletesPctAllowed(double deletesPctAllowed) {
113+
regularMergePolicy.setDeletesPctAllowed(deletesPctAllowed);
114+
forcedMergePolicy.setDeletesPctAllowed(deletesPctAllowed);
115+
}
116+
117+
public double getDeletesPctAllowed() {
118+
return regularMergePolicy.getDeletesPctAllowed();
119+
}
111120
}

server/src/main/java/org/elasticsearch/index/IndexSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ public IndexSettings(final IndexMetaData indexMetaData, final Settings nodeSetti
466466
defaultPipeline = scopedSettings.get(DEFAULT_PIPELINE);
467467

468468
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_COMPOUND_FORMAT_SETTING, mergePolicyConfig::setNoCFSRatio);
469+
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING, mergePolicyConfig::setDeletesPctAllowed);
469470
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_EXPUNGE_DELETES_ALLOWED_SETTING, mergePolicyConfig::setExpungeDeletesAllowed);
470471
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_FLOOR_SEGMENT_SETTING, mergePolicyConfig::setFloorSegmentSetting);
471472
scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE_SETTING, mergePolicyConfig::setMaxMergesAtOnce);

server/src/main/java/org/elasticsearch/index/MergePolicyConfig.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,12 @@
8383
* &gt;= than the <code>max_merge_at_once</code> otherwise you'll force too many merges to
8484
* occur.
8585
*
86-
* <li><code>index.merge.policy.reclaim_deletes_weight</code>:
86+
* <li><code>index.merge.policy.deletes_pct_allowed</code>:
8787
*
88-
* Controls how aggressively merges that reclaim more deletions are favored.
89-
* Higher values favor selecting merges that reclaim deletions. A value of
90-
* <code>0.0</code> means deletions don't impact merge selection. Defaults to <code>2.0</code>.
88+
* Controls the maximum percentage of deleted documents that is tolerated in
89+
* the index. Lower values make the index more space efficient at the
90+
* expense of increased CPU and I/O activity. Values must be between <code>20</code> and
91+
* <code>50</code>. Default value is <code>33</code>.
9192
* </ul>
9293
*
9394
* <p>
@@ -127,6 +128,7 @@ public final class MergePolicyConfig {
127128
public static final ByteSizeValue DEFAULT_MAX_MERGED_SEGMENT = new ByteSizeValue(5, ByteSizeUnit.GB);
128129
public static final double DEFAULT_SEGMENTS_PER_TIER = 10.0d;
129130
public static final double DEFAULT_RECLAIM_DELETES_WEIGHT = 2.0d;
131+
public static final double DEFAULT_DELETES_PCT_ALLOWED = 33.0d;
130132
public static final Setting<Double> INDEX_COMPOUND_FORMAT_SETTING =
131133
new Setting<>("index.compound_format", Double.toString(TieredMergePolicy.DEFAULT_NO_CFS_RATIO), MergePolicyConfig::parseNoCFSRatio,
132134
Property.Dynamic, Property.IndexScope);
@@ -152,6 +154,9 @@ public final class MergePolicyConfig {
152154
public static final Setting<Double> INDEX_MERGE_POLICY_RECLAIM_DELETES_WEIGHT_SETTING =
153155
Setting.doubleSetting("index.merge.policy.reclaim_deletes_weight", DEFAULT_RECLAIM_DELETES_WEIGHT, 0.0d,
154156
Property.Dynamic, Property.IndexScope, Property.Deprecated);
157+
public static final Setting<Double> INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING =
158+
Setting.doubleSetting("index.merge.policy.deletes_pct_allowed", DEFAULT_DELETES_PCT_ALLOWED, 20.0d, 50.0d,
159+
Property.Dynamic, Property.IndexScope);
155160
public static final String INDEX_MERGE_ENABLED = "index.merge.enabled"; // don't convert to Setting<> and register... we only set this in tests and register via a plugin
156161

157162

@@ -165,6 +170,7 @@ public final class MergePolicyConfig {
165170
ByteSizeValue maxMergedSegment = indexSettings.getValue(INDEX_MERGE_POLICY_MAX_MERGED_SEGMENT_SETTING);
166171
double segmentsPerTier = indexSettings.getValue(INDEX_MERGE_POLICY_SEGMENTS_PER_TIER_SETTING);
167172
double reclaimDeletesWeight = indexSettings.getValue(INDEX_MERGE_POLICY_RECLAIM_DELETES_WEIGHT_SETTING);
173+
double deletesPctAllowed = indexSettings.getValue(INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING);
168174
this.mergesEnabled = indexSettings.getSettings()
169175
.getAsBooleanLenientForPreEs6Indices(indexSettings.getIndexVersionCreated(), INDEX_MERGE_ENABLED, true, new DeprecationLogger(logger));
170176
if (mergesEnabled == false) {
@@ -178,9 +184,10 @@ public final class MergePolicyConfig {
178184
mergePolicy.setMaxMergeAtOnceExplicit(maxMergeAtOnceExplicit);
179185
mergePolicy.setMaxMergedSegmentMB(maxMergedSegment.getMbFrac());
180186
mergePolicy.setSegmentsPerTier(segmentsPerTier);
187+
mergePolicy.setDeletesPctAllowed(deletesPctAllowed);
181188
if (logger.isTraceEnabled()) {
182-
logger.trace("using [tiered] merge mergePolicy with expunge_deletes_allowed[{}], floor_segment[{}], max_merge_at_once[{}], max_merge_at_once_explicit[{}], max_merged_segment[{}], segments_per_tier[{}], reclaim_deletes_weight[{}]",
183-
forceMergeDeletesPctAllowed, floorSegment, maxMergeAtOnce, maxMergeAtOnceExplicit, maxMergedSegment, segmentsPerTier, reclaimDeletesWeight);
189+
logger.trace("using [tiered] merge mergePolicy with expunge_deletes_allowed[{}], floor_segment[{}], max_merge_at_once[{}], max_merge_at_once_explicit[{}], max_merged_segment[{}], segments_per_tier[{}], deletes_pct_allowed[{}]",
190+
forceMergeDeletesPctAllowed, floorSegment, maxMergeAtOnce, maxMergeAtOnceExplicit, maxMergedSegment, segmentsPerTier, deletesPctAllowed);
184191
}
185192
}
186193

@@ -212,6 +219,10 @@ void setNoCFSRatio(Double noCFSRatio) {
212219
mergePolicy.setNoCFSRatio(noCFSRatio);
213220
}
214221

222+
void setDeletesPctAllowed(Double deletesPctAllowed) {
223+
mergePolicy.setDeletesPctAllowed(deletesPctAllowed);
224+
}
225+
215226
private int adjustMaxMergeAtOnceIfNeeded(int maxMergeAtOnce, double segmentsPerTier) {
216227
// fixing maxMergeAtOnce, see TieredMergePolicy#setMaxMergeAtOnce
217228
if (!(segmentsPerTier >= maxMergeAtOnce)) {

server/src/test/java/org/elasticsearch/index/EsTieredMergePolicyTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,10 @@ public void testSetSegmentsPerTier() {
6969
policy.setSegmentsPerTier(42);
7070
assertEquals(42, policy.regularMergePolicy.getSegmentsPerTier(), 0);
7171
}
72+
73+
public void testSetDeletesPctAllowed() {
74+
EsTieredMergePolicy policy = new EsTieredMergePolicy();
75+
policy.setDeletesPctAllowed(42);
76+
assertEquals(42, policy.regularMergePolicy.getDeletesPctAllowed(), 0);
77+
}
7278
}

server/src/test/java/org/elasticsearch/index/MergePolicySettingsTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
3131
import static org.elasticsearch.index.IndexSettingsTests.newIndexMeta;
32+
import static org.hamcrest.Matchers.containsString;
3233
import static org.hamcrest.Matchers.equalTo;
3334

3435
public class MergePolicySettingsTests extends ESTestCase {
@@ -100,13 +101,22 @@ public void testTieredMergePolicySettingsUpdate() throws IOException {
100101
indexSettings.updateIndexMetaData(newIndexMeta("index", Settings.builder().put(MergePolicyConfig.INDEX_MERGE_POLICY_SEGMENTS_PER_TIER_SETTING.getKey(), MergePolicyConfig.DEFAULT_SEGMENTS_PER_TIER + 1).build()));
101102
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getSegmentsPerTier(), MergePolicyConfig.DEFAULT_SEGMENTS_PER_TIER + 1, 0);
102103

104+
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getDeletesPctAllowed(), MergePolicyConfig.DEFAULT_DELETES_PCT_ALLOWED, 0);
105+
indexSettings.updateIndexMetaData(newIndexMeta("index", Settings.builder().put(MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING.getKey(), 22).build()));
106+
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getDeletesPctAllowed(), 22, 0);
107+
108+
IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () ->
109+
indexSettings.updateIndexMetaData(newIndexMeta("index", Settings.builder().put(MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING.getKey(), 53).build())));
110+
final Throwable cause = exc.getCause();
111+
assertThat(cause.getMessage(), containsString("must be <= 50.0"));
103112
indexSettings.updateIndexMetaData(newIndexMeta("index", EMPTY_SETTINGS)); // see if defaults are restored
104113
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getForceMergeDeletesPctAllowed(), MergePolicyConfig.DEFAULT_EXPUNGE_DELETES_ALLOWED, 0.0d);
105114
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getFloorSegmentMB(), new ByteSizeValue(MergePolicyConfig.DEFAULT_FLOOR_SEGMENT.getMb(), ByteSizeUnit.MB).getMbFrac(), 0.00);
106115
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getMaxMergeAtOnce(), MergePolicyConfig.DEFAULT_MAX_MERGE_AT_ONCE);
107116
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getMaxMergeAtOnceExplicit(), MergePolicyConfig.DEFAULT_MAX_MERGE_AT_ONCE_EXPLICIT);
108117
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getMaxMergedSegmentMB(), new ByteSizeValue(MergePolicyConfig.DEFAULT_MAX_MERGED_SEGMENT.getBytes() + 1).getMbFrac(), 0.0001);
109118
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getSegmentsPerTier(), MergePolicyConfig.DEFAULT_SEGMENTS_PER_TIER, 0);
119+
assertEquals(((EsTieredMergePolicy) indexSettings.getMergePolicy()).getDeletesPctAllowed(), MergePolicyConfig.DEFAULT_DELETES_PCT_ALLOWED, 0);
110120
}
111121

112122
public Settings build(String value) {

0 commit comments

Comments
 (0)