Skip to content

Commit d41cf6a

Browse files
authored
Use delCount of SegmentInfos to calculate numDocs (#36323)
Today, we iterate the bitset of hardLiveDocs to calculate the number of live docs. This calculation might be expensive if we enable soft-deletes (by default) for old indices whose soft-deletes was disabled previously and had hard-deletes. Once soft-deletes is enabled, we no longer hard-update or hard-delete documents directly. We have hard-deletes in two scenarios: (1) from old segments where soft-deletes was disabled, (2) when IndexWriter hits non-aborted exceptions. These two cases, IW flushes SegmentInfos before exposing the hard-deletes; thus we can use the hard-delete count of SegmentInfos.
1 parent cc3872d commit d41cf6a

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

server/src/main/java/org/elasticsearch/common/lucene/Lucene.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -956,18 +956,17 @@ public CacheHelper getReaderCacheHelper() {
956956
super(in, new SubReaderWrapper() {
957957
@Override
958958
public LeafReader wrap(LeafReader leaf) {
959-
SegmentReader segmentReader = segmentReader(leaf);
960-
Bits hardLiveDocs = segmentReader.getHardLiveDocs();
959+
final SegmentReader segmentReader = segmentReader(leaf);
960+
final Bits hardLiveDocs = segmentReader.getHardLiveDocs();
961961
if (hardLiveDocs == null) {
962962
return new LeafReaderWithLiveDocs(leaf, null, leaf.maxDoc());
963963
}
964-
// TODO: Can we avoid calculate numDocs by using SegmentReader#getSegmentInfo with LUCENE-8458?
965-
int numDocs = 0;
966-
for (int i = 0; i < hardLiveDocs.length(); i++) {
967-
if (hardLiveDocs.get(i)) {
968-
numDocs++;
969-
}
970-
}
964+
// Once soft-deletes is enabled, we no longer hard-update or hard-delete documents directly.
965+
// Two scenarios that we have hard-deletes: (1) from old segments where soft-deletes was disabled,
966+
// (2) when IndexWriter hits non-aborted exceptions. These two cases, IW flushes SegmentInfos
967+
// before exposing the hard-deletes, thus we can use the hard-delete count of SegmentInfos.
968+
final int numDocs = segmentReader.maxDoc() - segmentReader.getSegmentInfo().getDelCount();
969+
assert numDocs == popCount(hardLiveDocs) : numDocs + " != " + popCount(hardLiveDocs);
971970
return new LeafReaderWithLiveDocs(segmentReader, hardLiveDocs, numDocs);
972971
}
973972
});
@@ -984,6 +983,17 @@ public CacheHelper getReaderCacheHelper() {
984983
}
985984
}
986985

986+
private static int popCount(Bits bits) {
987+
assert bits != null;
988+
int onBits = 0;
989+
for (int i = 0; i < bits.length(); i++) {
990+
if (bits.get(i)) {
991+
onBits++;
992+
}
993+
}
994+
return onBits;
995+
}
996+
987997
/**
988998
* Returns a numeric docvalues which can be used to soft-delete documents.
989999
*/

server/src/main/java/org/elasticsearch/index/engine/InternalEngine.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,6 +2585,11 @@ public long softUpdateDocuments(Term term, Iterable<? extends Iterable<? extends
25852585
assert softDeleteEnabled : "Call #softUpdateDocuments but soft-deletes is disabled";
25862586
return super.softUpdateDocuments(term, docs, softDeletes);
25872587
}
2588+
@Override
2589+
public long tryDeleteDocument(IndexReader readerIn, int docID) {
2590+
assert false : "#tryDeleteDocument is not supported. See Lucene#DirectoryReaderWithAllLiveDocs";
2591+
throw new UnsupportedOperationException();
2592+
}
25882593
}
25892594

25902595
/**

0 commit comments

Comments
 (0)