Skip to content

Commit 283bce2

Browse files
authored
Cache non-exist timeseries metadata to reduce IO (#16606)
* Cache non-exist timeseries metadata to reduce IO * Fix memory calculation * spotless * fix review * fix compilation
1 parent d328639 commit 283bce2

4 files changed

Lines changed: 344 additions & 2 deletions

File tree

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/DataNodeMemoryConfig.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ public class DataNodeMemoryConfig {
6161
/** whether to cache metadata(ChunkMetaData and TsFileMetaData) or not. */
6262
private boolean metaDataCacheEnable = true;
6363

64+
/**
65+
* If a timeseries is not found in a TsFile, also cache a placeholder to indicate the
66+
* non-existence.
67+
*/
68+
private boolean mayCacheNonExistSeries = true;
69+
6470
/** How many threads can concurrently execute query statement. When <= 0, use CPU core number. */
6571
private int queryThreadCount = Runtime.getRuntime().availableProcessors();
6672

@@ -412,6 +418,10 @@ private void initQueryEngineMemoryAllocate(
412418
Boolean.parseBoolean(
413419
properties.getProperty(
414420
"meta_data_cache_enable", Boolean.toString(isMetaDataCacheEnable()))));
421+
setMayCacheNonExistSeries(
422+
Boolean.parseBoolean(
423+
properties.getProperty(
424+
"may_cache_nonexist_series", Boolean.toString(isMayCacheNonExistSeries()))));
415425

416426
try {
417427
// update enable query memory estimation for memory control
@@ -562,6 +572,14 @@ public void setMetaDataCacheEnable(boolean metaDataCacheEnable) {
562572
this.metaDataCacheEnable = metaDataCacheEnable;
563573
}
564574

575+
public boolean isMayCacheNonExistSeries() {
576+
return mayCacheNonExistSeries;
577+
}
578+
579+
public void setMayCacheNonExistSeries(boolean mayCacheNonExistSeries) {
580+
this.mayCacheNonExistSeries = mayCacheNonExistSeries;
581+
}
582+
565583
public int getQueryThreadCount() {
566584
return queryThreadCount;
567585
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/buffer/TimeSeriesMetadataCache.java

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@
3636
import com.github.benmanes.caffeine.cache.Caffeine;
3737
import com.github.benmanes.caffeine.cache.Weigher;
3838
import org.apache.tsfile.common.constant.TsFileConstant;
39+
import org.apache.tsfile.enums.TSDataType;
3940
import org.apache.tsfile.file.metadata.IDeviceID;
4041
import org.apache.tsfile.file.metadata.TimeseriesMetadata;
42+
import org.apache.tsfile.file.metadata.statistics.Statistics;
4143
import org.apache.tsfile.read.TsFileSequenceReader;
4244
import org.apache.tsfile.utils.BloomFilter;
45+
import org.apache.tsfile.utils.PublicBAOS;
4346
import org.apache.tsfile.utils.RamUsageEstimator;
4447
import org.slf4j.Logger;
4548
import org.slf4j.LoggerFactory;
@@ -70,6 +73,14 @@ public class TimeSeriesMetadataCache {
7073
IoTDBDescriptor.getInstance().getMemoryConfig();
7174
private static final IMemoryBlock CACHE_MEMORY_BLOCK;
7275
private static final boolean CACHE_ENABLE = memoryConfig.isMetaDataCacheEnable();
76+
private static final TimeseriesMetadata NULL_EXISTS_CACHE_PLACE_HOLDER =
77+
new TimeseriesMetadata(
78+
(byte) 0,
79+
0,
80+
"",
81+
TSDataType.INT32,
82+
Statistics.getStatsByType(TSDataType.INT32),
83+
new PublicBAOS());
7384

7485
private final Cache<TimeSeriesMetadataCacheKey, TimeseriesMetadata> lruCache;
7586

@@ -79,6 +90,9 @@ public class TimeSeriesMetadataCache {
7990
Collections.synchronizedMap(new WeakHashMap<>());
8091
private static final String SEPARATOR = "$";
8192

93+
private final AtomicLong evictedExistingEntryCount = new AtomicLong(0);
94+
private final AtomicLong evictedNonExistingEntryCount = new AtomicLong(0);
95+
8296
static {
8397
CACHE_MEMORY_BLOCK =
8498
memoryConfig
@@ -99,8 +113,20 @@ private TimeSeriesMetadataCache() {
99113
.weigher(
100114
(Weigher<TimeSeriesMetadataCacheKey, TimeseriesMetadata>)
101115
(key, value) ->
102-
(int) (key.getRetainedSizeInBytes() + value.getRetainedSizeInBytes()))
116+
(int)
117+
(key.getRetainedSizeInBytes()
118+
+ (value == NULL_EXISTS_CACHE_PLACE_HOLDER
119+
? 0
120+
: value.getRetainedSizeInBytes())))
103121
.recordStats()
122+
.evictionListener(
123+
(k, v, c) -> {
124+
if (v == NULL_EXISTS_CACHE_PLACE_HOLDER) {
125+
evictedNonExistingEntryCount.incrementAndGet();
126+
} else {
127+
evictedExistingEntryCount.incrementAndGet();
128+
}
129+
})
104130
.build();
105131
// add metrics
106132
MetricService.getInstance().addMetricSet(new TimeSeriesMetadataCacheMetrics(this));
@@ -216,10 +242,15 @@ public TimeseriesMetadata get(
216242
timeseriesMetadata = metadata.getStatistics().getCount() == 0 ? null : metadata;
217243
}
218244
}
245+
if (timeseriesMetadata == null
246+
&& !ignoreNotExists
247+
&& memoryConfig.isMayCacheNonExistSeries()) {
248+
lruCache.put(key, NULL_EXISTS_CACHE_PLACE_HOLDER);
249+
}
219250
}
220251
}
221252
}
222-
if (timeseriesMetadata == null) {
253+
if (timeseriesMetadata == null || timeseriesMetadata == NULL_EXISTS_CACHE_PLACE_HOLDER) {
223254
if (debug) {
224255
DEBUG_LOGGER.info(StorageEngineMessages.FILE_NO_SUCH_TIME_SERIES, key);
225256
}
@@ -285,8 +316,16 @@ public double calculateBloomFilterHitRatio() {
285316

286317
/** clear LRUCache. */
287318
public void clear() {
319+
logger.info(
320+
"Evicted non-existing/existing series count: {}/{}({}), total request: {}",
321+
evictedNonExistingEntryCount.get(),
322+
evictedExistingEntryCount.get(),
323+
((double) evictedNonExistingEntryCount.get()) / evictedExistingEntryCount.get(),
324+
lruCache.stats().requestCount());
288325
lruCache.invalidateAll();
289326
lruCache.cleanUp();
327+
evictedNonExistingEntryCount.set(0);
328+
evictedExistingEntryCount.set(0);
290329
}
291330

292331
public void remove(TimeSeriesMetadataCacheKey key) {

0 commit comments

Comments
 (0)