You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by zy...@apache.org on 2022/08/21 10:04:50 UTC

[iotdb] branch master updated: Idtable supports getting time series from disk and deleting time series (#7024)

This is an automated email from the ASF dual-hosted git repository.

zyk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new e02c2be065 Idtable supports getting time series from disk and deleting time series (#7024)
e02c2be065 is described below

commit e02c2be06583f29f11285e244807983636e4db9c
Author: Jian Zhang <38...@users.noreply.github.com>
AuthorDate: Sun Aug 21 18:04:43 2022 +0800

    Idtable supports getting time series from disk and deleting time series (#7024)
    
    Idtable supports getting time series from disk and deleting time series (#7024)
---
 .../idtable/AppendOnlyDiskSchemaManager.java       | 94 ++++++++++++++++++++--
 .../apache/iotdb/db/metadata/idtable/IDTable.java  | 29 ++++++-
 .../db/metadata/idtable/IDTableHashmapImpl.java    | 63 +++++++++++++++
 .../db/metadata/idtable/IDiskSchemaManager.java    | 24 +++++-
 .../db/metadata/idtable/entry/DeviceEntry.java     |  6 +-
 .../db/metadata/idtable/entry/DiskSchemaEntry.java | 10 ++-
 .../db/metadata/idtable/entry/SchemaEntry.java     |  9 +++
 .../iotdb/db/metadata/idtable/IDTableTest.java     | 91 +++++++++++++++++++++
 8 files changed, 306 insertions(+), 20 deletions(-)

diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/AppendOnlyDiskSchemaManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/AppendOnlyDiskSchemaManager.java
index f7048841f3..7856444791 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/AppendOnlyDiskSchemaManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/AppendOnlyDiskSchemaManager.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.metadata.idtable;
 
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.utils.TestOnly;
+import org.apache.iotdb.db.metadata.idtable.entry.DeviceIDFactory;
 import org.apache.iotdb.db.metadata.idtable.entry.DiskSchemaEntry;
 import org.apache.iotdb.db.metadata.idtable.entry.SchemaEntry;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
@@ -36,8 +37,10 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.RandomAccessFile;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 /** store id table schema in append only file */
@@ -52,6 +55,8 @@ public class AppendOnlyDiskSchemaManager implements IDiskSchemaManager {
 
   FileOutputStream outputStream;
 
+  RandomAccessFile randomAccessFile;
+
   long loc;
 
   private static final Logger logger = LoggerFactory.getLogger(AppendOnlyDiskSchemaManager.class);
@@ -60,6 +65,7 @@ public class AppendOnlyDiskSchemaManager implements IDiskSchemaManager {
     try {
       initFile(dir);
       outputStream = new FileOutputStream(dataFile, true);
+      randomAccessFile = new RandomAccessFile(dataFile, "rw");
       // we write file version to new file
       if (loc == 0) {
         ReadWriteIOUtils.write(FILE_VERSION, outputStream);
@@ -145,13 +151,15 @@ public class AppendOnlyDiskSchemaManager implements IDiskSchemaManager {
 
       while (inputStream.available() > 0) {
         DiskSchemaEntry cur = DiskSchemaEntry.deserialize(inputStream);
-        SchemaEntry schemaEntry =
-            new SchemaEntry(
-                TSDataType.deserialize(cur.type),
-                TSEncoding.deserialize(cur.encoding),
-                CompressionType.deserialize(cur.compressor),
-                loc);
-        idTable.putSchemaEntry(cur.deviceID, cur.measurementName, schemaEntry, cur.isAligned);
+        if (!cur.deviceID.equals(DiskSchemaEntry.TOMBSTONE)) {
+          SchemaEntry schemaEntry =
+              new SchemaEntry(
+                  TSDataType.deserialize(cur.type),
+                  TSEncoding.deserialize(cur.encoding),
+                  CompressionType.deserialize(cur.compressor),
+                  loc);
+          idTable.putSchemaEntry(cur.deviceID, cur.measurementName, schemaEntry, cur.isAligned);
+        }
         loc += cur.entrySize;
       }
     } catch (IOException | MetadataException e) {
@@ -179,7 +187,9 @@ public class AppendOnlyDiskSchemaManager implements IDiskSchemaManager {
         try {
           maxCount--;
           DiskSchemaEntry cur = DiskSchemaEntry.deserialize(inputStream);
-          res.add(cur);
+          if (!cur.deviceID.equals(DiskSchemaEntry.TOMBSTONE)) {
+            res.add(cur);
+          }
         } catch (IOException e) {
           logger.debug("read finished");
           break;
@@ -190,10 +200,78 @@ public class AppendOnlyDiskSchemaManager implements IDiskSchemaManager {
     return res;
   }
 
+  /**
+   * get DiskSchemaEntries from disk file
+   *
+   * @param offsets the offset of each record on the disk file
+   * @return DiskSchemaEntries
+   */
+  @Override
+  public List<DiskSchemaEntry> getDiskSchemaEntriesByOffset(List<Long> offsets) {
+    List<DiskSchemaEntry> diskSchemaEntries = new ArrayList<>(offsets.size());
+    Collections.sort(offsets);
+    try {
+      for (long offset : offsets) {
+        diskSchemaEntries.add(getDiskSchemaEntryByOffset(offset));
+      }
+    } catch (IOException e) {
+      logger.error(e.getMessage());
+    }
+    return diskSchemaEntries;
+  }
+
+  /**
+   * delete DiskSchemaEntry on disk
+   *
+   * @param offset the offset of a record on the disk file
+   * @throws MetadataException
+   */
+  @Override
+  public void deleteDiskSchemaEntryByOffset(long offset) throws MetadataException {
+    try {
+      randomAccessFile.seek(offset + FILE_VERSION.length() + Integer.BYTES);
+      int strLength = randomAccessFile.readInt();
+      byte[] bytes = new byte[strLength];
+      // change the deviceID of the DiskSchemaEntry to be deleted to a tombstone: bytes=[0,...,0]
+      randomAccessFile.write(bytes, 0, strLength);
+    } catch (IOException e) {
+      logger.error(e.getMessage());
+      throw new MetadataException(e.getMessage());
+    }
+  }
+
+  private DiskSchemaEntry getDiskSchemaEntryByOffset(long offset) throws IOException {
+    randomAccessFile.seek(offset + FILE_VERSION.length() + Integer.BYTES);
+    // skip reading deviceID
+    readString();
+    String seriesKey = readString();
+    String measurementName = readString();
+    String deviceID =
+        DeviceIDFactory.getInstance()
+            .getDeviceID(seriesKey.substring(0, seriesKey.length() - measurementName.length() - 1))
+            .toStringID();
+    return new DiskSchemaEntry(
+        deviceID,
+        seriesKey,
+        measurementName,
+        randomAccessFile.readByte(),
+        randomAccessFile.readByte(),
+        randomAccessFile.readByte(),
+        randomAccessFile.readBoolean());
+  }
+
+  private String readString() throws IOException {
+    int strLength = randomAccessFile.readInt();
+    byte[] bytes = new byte[strLength];
+    randomAccessFile.read(bytes, 0, strLength);
+    return new String(bytes, 0, strLength);
+  }
+
   @Override
   public void close() throws IOException {
     try {
       outputStream.close();
+      randomAccessFile.close();
     } catch (IOException e) {
       logger.error("close schema file failed");
       throw e;
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTable.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTable.java
index 906f03edcc..fa44865e4e 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTable.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTable.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.metadata.idtable.entry.DeviceEntry;
 import org.apache.iotdb.db.metadata.idtable.entry.DeviceIDFactory;
+import org.apache.iotdb.db.metadata.idtable.entry.DiskSchemaEntry;
 import org.apache.iotdb.db.metadata.idtable.entry.IDeviceID;
 import org.apache.iotdb.db.metadata.idtable.entry.SchemaEntry;
 import org.apache.iotdb.db.metadata.idtable.entry.TimeseriesID;
@@ -36,6 +37,7 @@ import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateAlignedTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
+import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 
 import org.slf4j.Logger;
@@ -44,6 +46,7 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 public interface IDTable {
   /** logger */
@@ -68,6 +71,15 @@ public interface IDTable {
    */
   void createTimeseries(CreateTimeSeriesPlan plan) throws MetadataException;
 
+  /**
+   * Delete all timeseries matching the given paths
+   *
+   * @param fullPaths paths to be deleted
+   * @return deletion failed Timeseries
+   * @throws MetadataException
+   */
+  Pair<Integer, Set<String>> deleteTimeseries(List<PartialPath> fullPaths) throws MetadataException;
+
   /**
    * check inserting timeseries existence and fill their measurement mnode
    *
@@ -129,7 +141,7 @@ public interface IDTable {
    * @param deviceName device name of the time series
    * @return device entry of the timeseries
    */
-  public DeviceEntry getDeviceEntry(String deviceName);
+  DeviceEntry getDeviceEntry(String deviceName);
 
   /**
    * get schema from device and measurements
@@ -138,14 +150,14 @@ public interface IDTable {
    * @param measurementName measurement name of the time series
    * @return schema entry of the timeseries
    */
-  public IMeasurementSchema getSeriesSchema(String deviceName, String measurementName);
+  IMeasurementSchema getSeriesSchema(String deviceName, String measurementName);
 
   /**
    * get all device entries
    *
    * @return all device entries
    */
-  public List<DeviceEntry> getAllDeviceEntry();
+  List<DeviceEntry> getAllDeviceEntry();
 
   /**
    * put schema entry to id table, currently used in recover
@@ -155,7 +167,7 @@ public interface IDTable {
    * @param schemaEntry schema entry to put
    * @param isAligned is the device aligned
    */
-  public void putSchemaEntry(
+  void putSchemaEntry(
       String devicePath, String measurement, SchemaEntry schemaEntry, boolean isAligned)
       throws MetadataException;
 
@@ -194,6 +206,15 @@ public interface IDTable {
     }
   }
 
+  /**
+   * get DiskSchemaEntries from disk file
+   *
+   * @param schemaEntries get the disk pointers from schemaEntries
+   * @return DiskSchemaEntries
+   */
+  @TestOnly
+  List<DiskSchemaEntry> getDiskSchemaEntries(List<SchemaEntry> schemaEntries);
+
   @TestOnly
   Map<IDeviceID, DeviceEntry>[] getIdTables();
 
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTableHashmapImpl.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTableHashmapImpl.java
index 94b82f5ccd..af3cb4d9bc 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTableHashmapImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDTableHashmapImpl.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.metadata.DataTypeMismatchException;
 import org.apache.iotdb.db.metadata.idtable.entry.DeviceEntry;
 import org.apache.iotdb.db.metadata.idtable.entry.DeviceIDFactory;
+import org.apache.iotdb.db.metadata.idtable.entry.DiskSchemaEntry;
 import org.apache.iotdb.db.metadata.idtable.entry.IDeviceID;
 import org.apache.iotdb.db.metadata.idtable.entry.InsertMeasurementMNode;
 import org.apache.iotdb.db.metadata.idtable.entry.SchemaEntry;
@@ -38,6 +39,7 @@ import org.apache.iotdb.db.qp.physical.sys.CreateAlignedTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
 import org.apache.iotdb.db.service.IoTDB;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
+import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 
@@ -47,9 +49,12 @@ import org.slf4j.LoggerFactory;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /** id table belongs to a storage group and mapping timeseries path to it's schema */
 public class IDTableHashmapImpl implements IDTable {
@@ -129,6 +134,48 @@ public class IDTableHashmapImpl implements IDTable {
     deviceEntry.putSchemaEntry(plan.getPath().getMeasurement(), schemaEntry);
   }
 
+  /**
+   * Delete all timeseries matching the given paths
+   *
+   * @param fullPaths paths to be deleted
+   * @return deletion failed Timeseries
+   * @throws MetadataException
+   */
+  @Override
+  public synchronized Pair<Integer, Set<String>> deleteTimeseries(List<PartialPath> fullPaths)
+      throws MetadataException {
+    int deletedNum = 0;
+    Set<String> failedNames = new HashSet<>();
+    List<Pair<PartialPath, Long>> deletedPairs = new ArrayList<>(fullPaths.size());
+    for (PartialPath fullPath : fullPaths) {
+      Map<String, SchemaEntry> map = getDeviceEntry(fullPath.getDevice()).getMeasurementMap();
+      if (map == null) {
+        failedNames.add(fullPath.getFullPath());
+      } else {
+        SchemaEntry schemaEntry = map.get(fullPath.getMeasurement());
+        if (schemaEntry == null) {
+          failedNames.add(fullPath.getFullPath());
+        } else {
+          deletedPairs.add(new Pair<>(fullPath, schemaEntry.getDiskPointer()));
+        }
+      }
+    }
+    // Sort by the offset of the disk records,transpose the random I/O to the order I/O
+    deletedPairs.sort(Comparator.comparingLong(o -> o.right));
+    for (Pair<PartialPath, Long> pair : deletedPairs) {
+      try {
+        getIDiskSchemaManager().deleteDiskSchemaEntryByOffset(pair.right);
+        DeviceEntry deviceEntry = getDeviceEntry(pair.left.getDevice());
+        Map<String, SchemaEntry> map = getDeviceEntry(pair.left.getDevice()).getMeasurementMap();
+        map.keySet().remove(pair.left.getMeasurement());
+        deletedNum++;
+      } catch (MetadataException e) {
+        failedNames.add(pair.left.getFullPath());
+      }
+    }
+    return new Pair<>(deletedNum, failedNames);
+  }
+
   /**
    * check inserting timeseries existence and fill their measurement mnode
    *
@@ -326,6 +373,22 @@ public class IDTableHashmapImpl implements IDTable {
     deviceEntry.putSchemaEntry(measurement, schemaEntry);
   }
 
+  /**
+   * get DiskSchemaEntries from disk file
+   *
+   * @param schemaEntries get the disk pointers from schemaEntries
+   * @return DiskSchemaEntries
+   */
+  @Override
+  @TestOnly
+  public synchronized List<DiskSchemaEntry> getDiskSchemaEntries(List<SchemaEntry> schemaEntries) {
+    List<Long> offsets = new ArrayList<>(schemaEntries.size());
+    for (SchemaEntry schemaEntry : schemaEntries) {
+      offsets.add(schemaEntry.getDiskPointer());
+    }
+    return getIDiskSchemaManager().getDiskSchemaEntriesByOffset(offsets);
+  }
+
   /**
    * check whether a time series is exist if exist, check the type consistency if not exist, call
    * SchemaProcessor to create it
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDiskSchemaManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDiskSchemaManager.java
index a2f15d6d59..50f6f198a0 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDiskSchemaManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/IDiskSchemaManager.java
@@ -18,11 +18,13 @@
  */
 package org.apache.iotdb.db.metadata.idtable;
 
+import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.metadata.idtable.entry.DiskSchemaEntry;
 
 import java.io.IOException;
 import java.util.Collection;
+import java.util.List;
 
 /** This class manages IO of id table's schema entry */
 public interface IDiskSchemaManager {
@@ -33,14 +35,14 @@ public interface IDiskSchemaManager {
    * @param schemaEntry disk schema entry
    * @return disk position of that entry
    */
-  public long serialize(DiskSchemaEntry schemaEntry);
+  long serialize(DiskSchemaEntry schemaEntry);
 
   /**
    * recover id table from log file
    *
    * @param idTable id table need to be recovered
    */
-  public void recover(IDTable idTable);
+  void recover(IDTable idTable);
 
   /**
    * get all disk schema entries from file
@@ -48,7 +50,23 @@ public interface IDiskSchemaManager {
    * @return collection of all disk schema entires
    */
   @TestOnly
-  public Collection<DiskSchemaEntry> getAllSchemaEntry() throws IOException;
+  Collection<DiskSchemaEntry> getAllSchemaEntry() throws IOException;
+
+  /**
+   * get DiskSchemaEntries from disk file
+   *
+   * @param offsets the offset of each record on the disk file
+   * @return DiskSchemaEntries
+   */
+  List<DiskSchemaEntry> getDiskSchemaEntriesByOffset(List<Long> offsets);
+
+  /**
+   * delete DiskSchemaEntries on disk
+   *
+   * @param offset the offset of a record on the disk file
+   * @throws MetadataException
+   */
+  void deleteDiskSchemaEntryByOffset(long offset) throws MetadataException;
 
   /** close file and free resource */
   void close() throws IOException;
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DeviceEntry.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DeviceEntry.java
index 5a1d0c6005..3ef77edec7 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DeviceEntry.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DeviceEntry.java
@@ -19,11 +19,10 @@
 
 package org.apache.iotdb.db.metadata.idtable.entry;
 
-import org.apache.iotdb.commons.utils.TestOnly;
-
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
 
 /** device entry in id table */
 public class DeviceEntry {
@@ -47,7 +46,7 @@ public class DeviceEntry {
 
   public DeviceEntry(IDeviceID deviceID) {
     this.deviceID = deviceID;
-    measurementMap = new HashMap<>();
+    measurementMap = new ConcurrentHashMap<>();
     lastTimeMapOfEachPartition = new HashMap<>();
     flushTimeMapOfEachPartition = new HashMap<>();
   }
@@ -150,7 +149,6 @@ public class DeviceEntry {
   }
   // endregion
 
-  @TestOnly
   public Map<String, SchemaEntry> getMeasurementMap() {
     return measurementMap;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DiskSchemaEntry.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DiskSchemaEntry.java
index 556759b2f8..e0e21ddbfa 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DiskSchemaEntry.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/DiskSchemaEntry.java
@@ -29,6 +29,8 @@ import java.io.OutputStream;
  * the disk schema entry of schema entry of id table. This is a po class, so every field is public
  */
 public class DiskSchemaEntry {
+
+  public static final String TOMBSTONE = "tombstone_record";
   // id form device path, eg: 1#2#3#4
   public String deviceID;
 
@@ -100,10 +102,16 @@ public class DiskSchemaEntry {
     // read byte len
     res.entrySize = ReadWriteIOUtils.readInt(inputStream);
     res.entrySize += Integer.BYTES;
-
+    if (isTombstone(res.deviceID)) res.deviceID = TOMBSTONE;
     return res;
   }
 
+  private static Boolean isTombstone(String deviceID) {
+    int length = deviceID.getBytes().length;
+    byte[] bytes = new byte[length];
+    return deviceID.equals(new String(bytes, 0, length));
+  }
+
   @Override
   public String toString() {
     return "DiskSchemaEntry{"
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/SchemaEntry.java b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/SchemaEntry.java
index dfd26f786e..bf95324a4b 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/SchemaEntry.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/SchemaEntry.java
@@ -109,6 +109,15 @@ public class SchemaEntry implements ILastCacheContainer {
     }
   }
 
+  /**
+   * get disk pointer of ts from long value of schema
+   *
+   * @return disk pointer
+   */
+  public long getDiskPointer() {
+    return schema >> 25;
+  }
+
   /**
    * get ts data type from long value of schema
    *
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/idtable/IDTableTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/idtable/IDTableTest.java
index f3e2ab90b2..2ea9f8cd35 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/idtable/IDTableTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/idtable/IDTableTest.java
@@ -27,6 +27,10 @@ import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.DataTypeMismatchException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.LocalSchemaProcessor;
+import org.apache.iotdb.db.metadata.idtable.entry.DeviceIDFactory;
+import org.apache.iotdb.db.metadata.idtable.entry.DiskSchemaEntry;
+import org.apache.iotdb.db.metadata.idtable.entry.IDeviceID;
+import org.apache.iotdb.db.metadata.idtable.entry.SchemaEntry;
 import org.apache.iotdb.db.metadata.lastCache.container.ILastCacheContainer;
 import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
 import org.apache.iotdb.db.qp.Planner;
@@ -41,6 +45,7 @@ import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
+import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.utils.TsPrimitiveType;
 
 import org.junit.After;
@@ -48,10 +53,16 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
+import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -596,6 +607,86 @@ public class IDTableTest {
     }
   }
 
+  @Test
+  public void testGetDiskSchemaEntries() {
+    try {
+      IDTable idTable = IDTableManager.getInstance().getIDTable(new PartialPath("root.laptop"));
+      String sgPath = "root.laptop";
+      for (int i = 0; i < 10; i++) {
+        String devicePath = sgPath + ".d" + i;
+        IDeviceID iDeviceID = DeviceIDFactory.getInstance().getDeviceID(devicePath);
+        String measurement = "s" + i;
+        idTable.putSchemaEntry(
+            devicePath,
+            measurement,
+            new SchemaEntry(
+                TSDataType.BOOLEAN,
+                TSEncoding.BITMAP,
+                CompressionType.UNCOMPRESSED,
+                iDeviceID,
+                new PartialPath(devicePath + "." + measurement),
+                false,
+                idTable.getIDiskSchemaManager()),
+            false);
+        SchemaEntry schemaEntry =
+            idTable.getDeviceEntry(iDeviceID.toStringID()).getSchemaEntry(measurement);
+        List<SchemaEntry> schemaEntries = new ArrayList<>();
+        schemaEntries.add(schemaEntry);
+        List<DiskSchemaEntry> diskSchemaEntries = idTable.getDiskSchemaEntries(schemaEntries);
+        assertNotNull(diskSchemaEntries);
+        assertEquals(diskSchemaEntries.size(), 1);
+        assertEquals(diskSchemaEntries.get(0).seriesKey, devicePath + "." + measurement);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail("throw exception");
+    }
+  }
+
+  @Test
+  public void testDeleteTimeseries() {
+    try {
+      IDTable idTable = IDTableManager.getInstance().getIDTable(new PartialPath("root.laptop"));
+      String sgPath = "root.laptop";
+      for (int i = 0; i < 10; i++) {
+        String devicePath = sgPath + ".d" + i;
+        IDeviceID iDeviceID = DeviceIDFactory.getInstance().getDeviceID(devicePath);
+        String measurement = "s" + i;
+        SchemaEntry schemaEntry =
+            new SchemaEntry(
+                TSDataType.BOOLEAN,
+                TSEncoding.BITMAP,
+                CompressionType.UNCOMPRESSED,
+                iDeviceID,
+                new PartialPath(devicePath + "." + measurement),
+                false,
+                idTable.getIDiskSchemaManager());
+        idTable.putSchemaEntry(devicePath, measurement, schemaEntry, false);
+      }
+      List<PartialPath> partialPaths = new ArrayList<>();
+      partialPaths.add(new PartialPath("root.laptop.d0.s0"));
+      partialPaths.add(new PartialPath("root.laptop.d8.s8"));
+      partialPaths.add(new PartialPath("root.laptop.d2.s3"));
+      Pair<Integer, Set<String>> pairs = idTable.deleteTimeseries(partialPaths);
+      assertNotNull(pairs);
+      assertEquals((int) pairs.left, 2);
+      assertTrue(pairs.right.contains("root.laptop.d2.s3"));
+      assertFalse(pairs.right.contains("root.laptop.d0.s0"));
+      assertFalse(pairs.right.contains("root.laptop.d8.s8"));
+      Collection<DiskSchemaEntry> diskSchemaEntries =
+          idTable.getIDiskSchemaManager().getAllSchemaEntry();
+      for (DiskSchemaEntry diskSchemaEntry : diskSchemaEntries) {
+        assertNotEquals("root.laptop.d0.s0", diskSchemaEntry.seriesKey);
+        assertNotEquals("root.laptop.d8.s8", diskSchemaEntry.seriesKey);
+      }
+      assertNull(idTable.getDeviceEntry("root.laptop.d0").getMeasurementMap().get("s0"));
+      assertNull(idTable.getDeviceEntry("root.laptop.d8").getMeasurementMap().get("s1"));
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail("throw exception");
+    }
+  }
+
   @Test
   public void testFlushTimeAndLastCache() {
     LocalSchemaProcessor schemaProcessor = IoTDB.schemaProcessor;