Skip to content

Commit 7adb5d6

Browse files
authored
Decrease TieredMergePolicy's default number of segments per tier to 8. (#14823)
`TieredMergePolicy` currently allows 10 segments per tier. With Lucene being increasingly deployed with separate indexing and search tiers that get updated via segment-based replication, I believe that it would make sense for Lucene to have more aggressive merging defaults, a price that is only paid once on the indexing tier, but that benefits all search nodes that serve queries for this index. Note that this is still a somewhat conservative default, applications with low latency requirements and low update rates will likely want to go even further, with 4 segments per tier, or even 2. `BaseMergePolicyTestCase#testSimulateAppendOnly` reports a write amplification increase from 3.4 to 3.8, while `BaseMergePolicyTestCase#testSimulateUpdates` reports a write amplification increase from 4.5 to 4.9. In exchange, the number of segments between the floor and max segment sizes decreases by about 20%. This should especially help queries that have a high per-segment overhead: PK lookups, point queries, multi-term queries and vector searches.
1 parent e5eb7e7 commit 7adb5d6

File tree

3 files changed

+19
-13
lines changed

3 files changed

+19
-13
lines changed

lucene/CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ Optimizations
194194

195195
* GITHUB#14854: Using BatchScoreBulkScorer on CombinedFieldQuery. (Ge Song)
196196

197+
Changes in Runtime Behavior
198+
---------------------
199+
* GITHUB#14823: Decrease TieredMergePolicy's default number of segments per
200+
tier from 10 to 8. This is expected to result in slightly faster search and
201+
slightly slower indexing. (Adrien Grand)
202+
197203
Bug Fixes
198204
---------------------
199205
* GITHUB#14654: ValueSource.fromDoubleValuesSource(dvs).getSortField() would throw errors when

lucene/core/src/java/org/apache/lucene/index/TieredMergePolicy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public class TieredMergePolicy extends MergePolicy {
8585
private long maxMergedSegmentBytes = 5 * 1024 * 1024 * 1024L;
8686

8787
private long floorSegmentBytes = 16 * 1024 * 1024L;
88-
private double segsPerTier = 10.0;
88+
private double segsPerTier = 8.0;
8989
private double forceMergeDeletesPctAllowed = 10.0;
9090
private double deletesPctAllowed = 20.0;
9191
private int targetSearchConcurrency = 1;
@@ -217,7 +217,7 @@ public double getForceMergeDeletesPctAllowed() {
217217
* Sets the allowed number of segments per tier. Smaller values mean more merging but fewer
218218
* segments.
219219
*
220-
* <p>Default is 10.0.
220+
* <p>Default is 8.0.
221221
*/
222222
public TieredMergePolicy setSegmentsPerTier(double v) {
223223
if (v < 2.0) {

lucene/core/src/test/org/apache/lucene/index/TestTieredMergePolicy.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ public void testUnbalancedMergeSelection() throws Exception {
839839
// Make sure TMP always merged equal-number-of-docs segments:
840840
for (LeafReaderContext ctx : r.leaves()) {
841841
int numDocs = ctx.reader().numDocs();
842-
assertTrue("got numDocs=" + numDocs, numDocs == 100 || numDocs == 1000 || numDocs == 10000);
842+
assertTrue("got numDocs=" + numDocs, numDocs == 100 || numDocs == 800 || numDocs == 6400);
843843
}
844844
r.close();
845845
w.close();
@@ -883,7 +883,7 @@ public void testManyMaxSizeSegments() throws IOException {
883883
assertNotNull(mergeSpec);
884884
assertEquals(1, mergeSpec.merges.size());
885885
OneMerge merge = mergeSpec.merges.get(0);
886-
assertEquals(10, merge.segments.size());
886+
assertEquals(8, merge.segments.size());
887887
}
888888

889889
/** Make sure that singleton merges are considered when the max number of deletes is crossed. */
@@ -936,15 +936,15 @@ public void testMergeSizeIsLessThanFloorSize() throws IOException {
936936
MergeContext mergeContext = new MockMergeContext(SegmentCommitInfo::getDelCount);
937937

938938
SegmentInfos infos = new SegmentInfos(Version.LATEST.major);
939-
// 50 1MB segments
940-
for (int i = 0; i < 50; ++i) {
939+
// 5*mergeFactor 1MB segments
940+
for (int i = 0; i < 5 * 8; ++i) {
941941
infos.add(makeSegmentCommitInfo("_0", 1_000_000, 0, 1, IndexWriter.SOURCE_FLUSH));
942942
}
943943

944944
TieredMergePolicy mergePolicy = new TieredMergePolicy();
945945
mergePolicy.setFloorSegmentMB(0.1);
946946

947-
// Segments are above the floor segment size, we get 4 merges of mergeFactor=10 segments each
947+
// Segments are above the floor segment size, we get 4 merges of mergeFactor=8 segments each
948948
MergeSpecification mergeSpec =
949949
mergePolicy.findMerges(MergeTrigger.FULL_FLUSH, infos, mergeContext);
950950
assertNotNull(mergeSpec);
@@ -953,23 +953,23 @@ public void testMergeSizeIsLessThanFloorSize() throws IOException {
953953
assertEquals(mergePolicy.getSegmentsPerTier(), oneMerge.segments.size(), 0d);
954954
}
955955

956-
// Segments are below the floor segment size and it takes 15 segments to go above the floor
957-
// segment size. We get 3 merges of 15 segments each
958-
mergePolicy.setFloorSegmentMB(15);
956+
// Segments are below the floor segment size and it takes 12 segments to go above the floor
957+
// segment size. We get 3 merges of 12 segments each.
958+
mergePolicy.setFloorSegmentMB(12);
959959
mergeSpec = mergePolicy.findMerges(MergeTrigger.FULL_FLUSH, infos, mergeContext);
960960
assertNotNull(mergeSpec);
961961
assertEquals(3, mergeSpec.merges.size());
962962
for (OneMerge oneMerge : mergeSpec.merges) {
963-
assertEquals(15, oneMerge.segments.size());
963+
assertEquals(12, oneMerge.segments.size());
964964
}
965965

966-
// Segments are below the floor segment size. We get one merge that merges the 50 segments
966+
// Segments are below the floor segment size. We get one merge that merges the 40 segments
967967
// together.
968968
mergePolicy.setFloorSegmentMB(60);
969969
mergeSpec = mergePolicy.findMerges(MergeTrigger.FULL_FLUSH, infos, mergeContext);
970970
assertNotNull(mergeSpec);
971971
assertEquals(1, mergeSpec.merges.size());
972-
assertEquals(50, mergeSpec.merges.get(0).segments.size());
972+
assertEquals(40, mergeSpec.merges.get(0).segments.size());
973973
}
974974

975975
@SuppressWarnings("UnnecessaryAsync")

0 commit comments

Comments
 (0)