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

qiaojialin 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 102bd16  [IOTDB-829] Accelerate delete timeseries (#1732)
102bd16 is described below

commit 102bd1656c39e05e91ae492c31f6ca5389e19965
Author: wshao08 <[email protected]>
AuthorDate: Mon Oct 19 12:02:29 2020 +0800

    [IOTDB-829] Accelerate delete timeseries (#1732)
---
 .../org/apache/iotdb/db/engine/StorageEngine.java  |  28 +++---
 .../iotdb/db/engine/memtable/AbstractMemTable.java |  33 ++++---
 .../apache/iotdb/db/engine/memtable/IMemTable.java |   9 +-
 .../db/engine/merge/manage/MergeResource.java      |  10 +-
 .../engine/storagegroup/StorageGroupProcessor.java | 101 +++++++++++----------
 .../db/engine/storagegroup/TsFileProcessor.java    |  19 ++--
 .../org/apache/iotdb/db/metadata/MManager.java     |   5 +
 .../java/org/apache/iotdb/db/metadata/MTree.java   |  42 +++++++--
 .../org/apache/iotdb/db/metadata/PartialPath.java  |  53 ++++++++++-
 .../org/apache/iotdb/db/monitor/StatMonitor.java   |   2 +-
 .../apache/iotdb/db/qp/executor/PlanExecutor.java  |  25 +----
 .../iotdb/db/query/context/QueryContext.java       |   7 +-
 .../chunk/metadata/DiskChunkMetadataLoader.java    |   7 +-
 .../org/apache/iotdb/db/utils/FileLoaderUtils.java |   2 +-
 .../iotdb/db/writelog/recover/LogReplayer.java     |  11 ++-
 .../engine/modification/DeletionFileNodeTest.java  |  28 +++---
 .../db/engine/modification/DeletionQueryTest.java  |  52 +++++------
 .../storagegroup/StorageGroupProcessorTest.java    |   5 +-
 .../engine/storagegroup/TsFileProcessorTest.java   |   9 +-
 .../org/apache/iotdb/db/metadata/MTreeTest.java    |  21 +++++
 .../apache/iotdb/db/metadata/PartialPathTest.java  |  27 +++++-
 21 files changed, 320 insertions(+), 176 deletions(-)

diff --git a/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java 
b/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java
index 88cd7c7..0823608 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java
@@ -447,15 +447,16 @@ public class StorageEngine implements IService {
     // TODO
   }
 
-  /**
-   * delete data of timeseries "{deviceId}.{measurementId}" with time <= 
timestamp.
-   */
-  public void delete(PartialPath deviceId, String measurementId, long 
startTime, long endTime)
-      throws StorageEngineException {
-    StorageGroupProcessor storageGroupProcessor = getProcessor(deviceId);
+  public void delete(PartialPath path, long startTime, long endTime)
+          throws StorageEngineException {
     try {
-      storageGroupProcessor.delete(deviceId, measurementId, startTime, 
endTime);
-    } catch (IOException e) {
+      List<PartialPath> sgPaths = 
IoTDB.metaManager.searchAllRelatedStorageGroups(path);
+      for (PartialPath storageGroupPath : sgPaths) {
+        StorageGroupProcessor storageGroupProcessor = 
getProcessor(storageGroupPath);
+        PartialPath newPath = path.alterPrefixPath(storageGroupPath);
+        storageGroupProcessor.delete(newPath, startTime, endTime);
+      }
+    } catch (IOException | MetadataException e) {
       throw new StorageEngineException(e.getMessage());
     }
   }
@@ -463,12 +464,15 @@ public class StorageEngine implements IService {
   /**
    * delete data of timeseries "{deviceId}.{measurementId}"
    */
-  public void deleteTimeseries(PartialPath deviceId, String measurementId)
+  public void deleteTimeseries(PartialPath path)
       throws StorageEngineException {
-    StorageGroupProcessor storageGroupProcessor = getProcessor(deviceId);
     try {
-      storageGroupProcessor.delete(deviceId, measurementId, Long.MIN_VALUE, 
Long.MAX_VALUE);
-    } catch (IOException e) {
+      for (PartialPath storageGroupPath : 
IoTDB.metaManager.searchAllRelatedStorageGroups(path)) {
+        StorageGroupProcessor storageGroupProcessor = 
getProcessor(storageGroupPath);
+        PartialPath newPath = path.alterPrefixPath(storageGroupPath);
+        storageGroupProcessor.delete(newPath, Long.MIN_VALUE, Long.MAX_VALUE);
+      }
+    } catch (IOException | MetadataException e) {
       throw new StorageEngineException(e.getMessage());
     }
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
index e52dd1c..2a17107 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
@@ -21,15 +21,18 @@ package org.apache.iotdb.db.engine.memtable;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.modification.Deletion;
 import org.apache.iotdb.db.engine.modification.Modification;
 import org.apache.iotdb.db.engine.querycontext.ReadOnlyMemChunk;
 import org.apache.iotdb.db.exception.WriteProcessException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.PartialPath;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
 import org.apache.iotdb.db.rescon.TVListAllocator;
@@ -230,20 +233,24 @@ public abstract class AbstractMemTable implements 
IMemTable {
   }
 
   @Override
-  public void delete(String deviceId, String measurementId, long 
startTimestamp, long endTimestamp) {
-    Map<String, IWritableMemChunk> deviceMap = memTableMap.get(deviceId);
-    if (deviceMap != null) {
-      IWritableMemChunk chunk = deviceMap.get(measurementId);
-      if (chunk == null) {
-        return;
-      }
-      // If startTimestamp == Long.MIN_VALUE && endTimestamp == Long.MAX_VALUE,
-      // it means that the whole timeseries is deleted
-      if (startTimestamp == Long.MIN_VALUE && endTimestamp == Long.MAX_VALUE) {
-        deviceMap.remove(measurementId);
+  public void delete(PartialPath originalPath, PartialPath devicePath, long 
startTimestamp, long endTimestamp) {
+    Map<String, IWritableMemChunk> deviceMap = 
memTableMap.get(devicePath.getFullPath());
+    if (deviceMap == null) {
+      return;
+    }
+
+    Iterator<Entry<String, IWritableMemChunk>> iter = 
deviceMap.entrySet().iterator();
+    while (iter.hasNext()) {
+      Entry<String, IWritableMemChunk> entry = iter.next();
+      IWritableMemChunk chunk = entry.getValue();
+      PartialPath fullPath = devicePath.concatNode(entry.getKey());
+      if (originalPath.matchFullPath(fullPath)) {
+        if (startTimestamp == Long.MIN_VALUE && endTimestamp == 
Long.MAX_VALUE) {
+          iter.remove();
+        }
+        int deletedPointsNumber = chunk.delete(startTimestamp, endTimestamp);
+        totalPointsNum -= deletedPointsNumber;
       }
-      int deletedPointsNumber = chunk.delete(startTimestamp, endTimestamp);
-      totalPointsNum -= deletedPointsNumber;
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/IMemTable.java 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/IMemTable.java
index c291471..3cadfd9 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/memtable/IMemTable.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/memtable/IMemTable.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.db.engine.modification.Deletion;
 import org.apache.iotdb.db.engine.querycontext.ReadOnlyMemChunk;
 import org.apache.iotdb.db.exception.WriteProcessException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.PartialPath;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -87,14 +88,14 @@ public interface IMemTable {
 
   /**
    * Delete data in it whose timestamp <= 'timestamp' and belonging to 
timeseries
-   * deviceId.measurementId. Only called for non-flushing MemTable.
+   * path. Only called for non-flushing MemTable.
    *
-   * @param deviceId the deviceId of the timeseries to be deleted.
-   * @param measurementId the measurementId of the timeseries to be deleted.
+   * @param path the PartialPath the timeseries to be deleted.
+   * @param devicePath the device path of the timeseries to be deleted.
    * @param startTimestamp the lower-bound of deletion time.
    * @param endTimestamp the upper-bound of deletion time
    */
-  void delete(String deviceId, String measurementId, long startTimestamp, long 
endTimestamp);
+  void delete(PartialPath path, PartialPath devicePath, long startTimestamp, 
long endTimestamp);
 
   /**
    * Delete data in it whose timestamp <= 'timestamp' and belonging to 
timeseries
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/merge/manage/MergeResource.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/merge/manage/MergeResource.java
index 8b27ba8..46f93b0 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/merge/manage/MergeResource.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/merge/manage/MergeResource.java
@@ -25,11 +25,13 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import org.apache.iotdb.db.engine.modification.Modification;
@@ -170,9 +172,7 @@ public class MergeResource {
   }
 
   /**
-   * Get the modifications of a timeseries in the ModificationFile of a 
TsFile. Once the
-   * modifications of the timeseries are found out, they will be removed from 
the list to boost
-   * the next query, so two calls of the same file and timeseries are 
forbidden.
+   * Get the modifications of a timeseries in the ModificationFile of a TsFile.
    * @param path name of the time series
    */
   public List<Modification> getModifications(TsFileResource tsFileResource, 
PartialPath path) {
@@ -181,12 +181,10 @@ public class MergeResource {
         resource -> new 
LinkedList<>(resource.getModFile().getModifications()));
     List<Modification> pathModifications = new ArrayList<>();
     Iterator<Modification> modificationIterator = modifications.iterator();
-    // each path is visited only once in a merge, so the modifications can be 
removed after visiting
     while (modificationIterator.hasNext()) {
       Modification modification = modificationIterator.next();
-      if (modification.getPath().equals(path)) {
+      if (modification.getPath().matchFullPath(path)) {
         pathModifications.add(modification);
-        modificationIterator.remove();
       }
     }
     return pathModifications;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
index 28783ac..9e8f4ef 100755
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
@@ -1360,18 +1360,15 @@ public class StorageGroupProcessor {
     return true;
   }
 
-
   /**
    * Delete data whose timestamp <= 'timestamp' and belongs to the time series
    * deviceId.measurementId.
    *
-   * @param deviceId      the deviceId of the timeseries to be deleted.
-   * @param measurementId the measurementId of the timeseries to be deleted.
-   * @param startTime     the startTime of delete range.
-   * @param endTime       the endTime of delete range.
+   * @param path the timeseries path of the to be deleted.
+   * @param startTime the startTime of delete range.
+   * @param endTime the endTime of delete range.
    */
-  public void delete(PartialPath deviceId, String measurementId, long 
startTime, long endTime)
-      throws IOException {
+  public void delete(PartialPath path, long startTime, long endTime) throws 
IOException {
     // TODO: how to avoid partial deletion?
     // FIXME: notice that if we may remove a SGProcessor out of memory, we 
need to close all opened
     //mod files in mergingModification, sequenceFileList, and 
unsequenceFileList
@@ -1383,33 +1380,35 @@ public class StorageGroupProcessor {
     List<ModificationFile> updatedModFiles = new ArrayList<>();
 
     try {
-      Long lastUpdateTime = null;
-      for (Map<String, Long> latestTimeMap : latestTimeForEachDevice.values()) 
{
-        Long curTime = latestTimeMap.get(deviceId.getFullPath());
-        if (curTime != null && (lastUpdateTime == null || lastUpdateTime < 
curTime)) {
-          lastUpdateTime = curTime;
+      Set<PartialPath> devicePaths = 
IoTDB.metaManager.getDevices(path.getDevicePath());
+      for (PartialPath device : devicePaths) {
+        Long lastUpdateTime = null;
+        for (Map<String, Long> latestTimeMap : 
latestTimeForEachDevice.values()) {
+          Long curTime = latestTimeMap.get(device.getFullPath());
+          if (curTime != null && (lastUpdateTime == null || lastUpdateTime < 
curTime)) {
+            lastUpdateTime = curTime;
+          }
         }
-      }
-
-      // There is no tsfile data, the delete operation is invalid
-      if (lastUpdateTime == null) {
-        logger.debug("No device {} in SG {}, deletion invalid", deviceId, 
storageGroupName);
-        return;
+        // There is no tsfile data, the delete operation is invalid
+        if (lastUpdateTime == null) {
+          logger.debug("No device {} in SG {}, deletion invalid", device, 
storageGroupName);
+          return;
+        }
+        // delete Last cache record if necessary
+        tryToDeleteLastCache(device, path, startTime, endTime);
       }
 
       // write log to impacted working TsFileProcessors
-      logDeletion(startTime, endTime, deviceId, measurementId);
-      // delete Last cache record if necessary
-      tryToDeleteLastCache(deviceId, measurementId, startTime, endTime);
-      Deletion deletion = new Deletion(deviceId.concatNode(measurementId),
-          MERGE_MOD_START_VERSION_NUM, startTime, endTime);
+      logDeletion(startTime, endTime, path);
+
+      Deletion deletion = new Deletion(path, MERGE_MOD_START_VERSION_NUM, 
startTime, endTime);
       if (mergingModification != null) {
         mergingModification.write(deletion);
         updatedModFiles.add(mergingModification);
       }
 
-      deleteDataInFiles(tsFileManagement.getTsFileList(true), deletion, 
updatedModFiles);
-      deleteDataInFiles(tsFileManagement.getTsFileList(false), deletion, 
updatedModFiles);
+      deleteDataInFiles(tsFileManagement.getTsFileList(true), deletion, 
devicePaths, updatedModFiles);
+      deleteDataInFiles(tsFileManagement.getTsFileList(false), deletion, 
devicePaths, updatedModFiles);
 
     } catch (Exception e) {
       // roll back
@@ -1424,13 +1423,12 @@ public class StorageGroupProcessor {
     }
   }
 
-  private void logDeletion(long startTime, long endTime, PartialPath deviceId, 
String measurementId)
+  private void logDeletion(long startTime, long endTime, PartialPath path)
       throws IOException {
     long timePartitionStartId = StorageEngine.getTimePartition(startTime);
     long timePartitionEndId = StorageEngine.getTimePartition(endTime);
     if (IoTDBDescriptor.getInstance().getConfig().isEnableWal()) {
-      DeletePlan deletionPlan = new DeletePlan(startTime, endTime,
-          deviceId.concatNode(measurementId));
+      DeletePlan deletionPlan = new DeletePlan(startTime, endTime, path);
       for (Map.Entry<Long, TsFileProcessor> entry : 
workSequenceTsFileProcessors.entrySet()) {
         if (timePartitionStartId <= entry.getKey() && entry.getKey() <= 
timePartitionEndId) {
           entry.getValue().getLogNode().write(deletionPlan);
@@ -1445,15 +1443,23 @@ public class StorageGroupProcessor {
     }
   }
 
+  private boolean canSkipDelete(TsFileResource tsFileResource, 
Set<PartialPath> devicePaths,
+       long deleteStart, long deleteEnd) {
+    for (PartialPath device : devicePaths) {
+      if (tsFileResource.containsDevice(device.getFullPath()) &&
+              (deleteEnd >= tsFileResource.getStartTime(device.getFullPath()) 
&&
+               deleteStart <= 
tsFileResource.getOrDefaultEndTime(device.getFullPath(), Long.MAX_VALUE))) {
+        return false;
+      }
+    }
+    return true;
+  }
 
   private void deleteDataInFiles(Collection<TsFileResource> 
tsFileResourceList, Deletion deletion,
-      List<ModificationFile> updatedModFiles)
-      throws IOException {
-    String deviceId = deletion.getDevice();
+      Set<PartialPath> devicePaths, List<ModificationFile> updatedModFiles)
+          throws IOException, MetadataException {
     for (TsFileResource tsFileResource : tsFileResourceList) {
-      if (!tsFileResource.containsDevice(deviceId) ||
-          deletion.getEndTime() < tsFileResource.getStartTime(deviceId) ||
-          deletion.getStartTime() > 
tsFileResource.getOrDefaultEndTime(deviceId, Long.MAX_VALUE)) {
+      if (canSkipDelete(tsFileResource, devicePaths, deletion.getStartTime(), 
deletion.getEndTime())) {
         continue;
       }
 
@@ -1468,7 +1474,7 @@ public class StorageGroupProcessor {
       // delete data in memory of unsealed file
       if (!tsFileResource.isClosed()) {
         TsFileProcessor tsfileProcessor = 
tsFileResource.getUnsealedFileProcessor();
-        tsfileProcessor.deleteDataInMemory(deletion);
+        tsfileProcessor.deleteDataInMemory(deletion, devicePaths);
       }
 
       // add a record in case of rollback
@@ -1476,18 +1482,21 @@ public class StorageGroupProcessor {
     }
   }
 
-  private void tryToDeleteLastCache(PartialPath deviceId, String 
measurementId, long startTime,
-      long endTime) throws WriteProcessException {
+  private void tryToDeleteLastCache(PartialPath deviceId, PartialPath 
originalPath,
+      long startTime, long endTime) throws WriteProcessException {
+    if (!IoTDBDescriptor.getInstance().getConfig().isLastCacheEnabled()) {
+      return;
+    }
     try {
-      MManager manager = MManager.getInstance();
-      MNode node = manager.getDeviceNodeWithAutoCreate(deviceId);
-
-      MNode measurementNode = node.getChild(measurementId);
-      if (measurementNode != null) {
-        TimeValuePair lastPair = ((MeasurementMNode) 
measurementNode).getCachedLast();
-        if (lastPair != null && startTime <= lastPair.getTimestamp()
-            && lastPair.getTimestamp() <= endTime) {
-          ((MeasurementMNode) measurementNode).resetCache();
+      MNode node = IoTDB.metaManager.getDeviceNode(deviceId);
+
+      for (MNode measurementNode : node.getChildren().values()) {
+        if (measurementNode != null && 
originalPath.matchFullPath(measurementNode.getPartialPath())) {
+          TimeValuePair lastPair = ((MeasurementMNode) 
measurementNode).getCachedLast();
+          if (lastPair != null && startTime <= lastPair.getTimestamp()
+              && lastPair.getTimestamp() <= endTime) {
+            ((MeasurementMNode) measurementNode).resetCache();
+          }
         }
       }
     } catch (MetadataException e) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessor.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessor.java
index bd48984..536e7cc 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessor.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -48,7 +49,11 @@ import 
org.apache.iotdb.db.engine.storagegroup.StorageGroupProcessor.UpdateEndTi
 import org.apache.iotdb.db.engine.version.VersionController;
 import org.apache.iotdb.db.exception.TsFileProcessorException;
 import org.apache.iotdb.db.exception.WriteProcessException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.MManager;
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.metadata.mnode.MNode;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
@@ -226,7 +231,8 @@ public class TsFileProcessor {
    * <p>
    * Delete data in both working MemTable and flushing MemTables.
    */
-  public void deleteDataInMemory(Deletion deletion) {
+  public void deleteDataInMemory(Deletion deletion, Set<PartialPath> 
devicePaths)
+          throws MetadataException {
     flushQueryLock.writeLock().lock();
     if (logger.isDebugEnabled()) {
       logger
@@ -234,9 +240,10 @@ public class TsFileProcessor {
     }
     try {
       if (workMemTable != null) {
-        workMemTable
-            .delete(deletion.getDevice(), deletion.getMeasurement(), 
deletion.getStartTime(),
-                deletion.getEndTime());
+        for (PartialPath device : devicePaths) {
+          workMemTable.delete(deletion.getPath(), device, 
deletion.getStartTime(),
+              deletion.getEndTime());
+        }
       }
       // flushing memTables are immutable, only record this deletion in these 
memTables for query
       for (IMemTable memTable : flushingMemTables) {
@@ -720,7 +727,7 @@ public class TsFileProcessor {
   @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity 
warning
   public void query(String deviceId, String measurementId, TSDataType 
dataType, TSEncoding encoding,
       Map<String, String> props, QueryContext context,
-      List<TsFileResource> tsfileResourcesForQuery) throws IOException {
+      List<TsFileResource> tsfileResourcesForQuery) throws IOException, 
MetadataException {
     if (logger.isDebugEnabled()) {
       logger.debug("{}: {} get flushQueryLock and vmMergeLock read lock", 
storageGroupName,
           tsFileResource.getTsFile().getName());
@@ -748,7 +755,7 @@ public class TsFileProcessor {
 
       ModificationFile modificationFile = tsFileResource.getModFile();
       List<Modification> modifications = 
context.getPathModifications(modificationFile,
-          deviceId + IoTDBConstant.PATH_SEPARATOR + measurementId);
+          new PartialPath(deviceId + IoTDBConstant.PATH_SEPARATOR + 
measurementId));
 
       List<ChunkMetadata> chunkMetadataList = writer
           .getVisibleMetadataList(deviceId, measurementId, dataType);
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index 73ce5db..efeb4af 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -700,6 +700,11 @@ public class MManager {
     return mtree.getAllStorageGroupPaths();
   }
 
+  public List<PartialPath> searchAllRelatedStorageGroups(PartialPath path)
+      throws MetadataException {
+      return mtree.searchAllRelatedStorageGroups(path);
+  }
+
   /**
    * Get all storage group under given prefixPath.
    *
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
index 0fe0a5e..09dffb0 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
@@ -630,7 +630,27 @@ public class MTree implements Serializable {
   }
 
   /**
-   * Get all storage group under give path
+   * Get the storage group that given path belonged to or under given path
+   * All related storage groups refer two cases:
+   * 1. Storage groups with a prefix that is identical to path, e.g. given 
path "root.sg1",
+   *    storage group "root.sg1.sg2" and "root.sg1.sg3" will be added into 
result list.
+   * 2. Storage group that this path belongs to, e.g. given path 
"root.sg1.d1", and it is in
+   *    storage group "root.sg1". Then we adds "root.sg1" into result list.
+   *
+   * @return a list contains all storage groups related to given path
+   */
+  List<PartialPath> searchAllRelatedStorageGroups(PartialPath path) throws 
MetadataException {
+    String[] nodes = path.getNodes();
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(path.getFullPath());
+    }
+    List<PartialPath> storageGroupPaths = new ArrayList<>();
+    findStorageGroupPaths(root, nodes, 1, "", storageGroupPaths, false);
+    return storageGroupPaths;
+  }
+
+  /**
+   * Get all storage group under given path
    *
    * @return a list contains all storage group names under give path
    */
@@ -640,22 +660,29 @@ public class MTree implements Serializable {
       throw new IllegalPathException(prefixPath.getFullPath());
     }
     List<PartialPath> storageGroupPaths = new ArrayList<>();
-    findStorageGroupPaths(root, nodes, 1, "", storageGroupPaths);
+    findStorageGroupPaths(root, nodes, 1, "", storageGroupPaths, true);
     return storageGroupPaths;
   }
 
   /**
    * Traverse the MTree to match all storage group with prefix path.
+   * When trying to find storage groups via a path, we divide into two cases:
+   * 1. This path is only regarded as a prefix, in other words, this path is 
part of the result
+   *    storage groups.
+   * 2. This path is a full path and we use this method to find its belonged 
storage group.
+   * When prefixOnly is set to true, storage group paths in 1 is only added 
into result,
+   * otherwise, both 1 and 2 are returned.
    *
    * @param node              the current traversing node
    * @param nodes             split the prefix path with '.'
    * @param idx               the current index of array nodes
    * @param parent            current parent path
    * @param storageGroupPaths store all matched storage group names
+   * @param prefixOnly        only return storage groups that start with this 
prefix path
    */
   private void findStorageGroupPaths(MNode node, String[] nodes, int idx, 
String parent,
-      List<PartialPath> storageGroupPaths) {
-    if (node instanceof StorageGroupMNode && idx >= nodes.length) {
+      List<PartialPath> storageGroupPaths, boolean prefixOnly) {
+    if (node instanceof StorageGroupMNode && (!prefixOnly || idx >= 
nodes.length)) {
       storageGroupPaths.add(node.getPartialPath());
       return;
     }
@@ -663,13 +690,14 @@ public class MTree implements Serializable {
     if (!(PATH_WILDCARD).equals(nodeReg)) {
       MNode next = node.getChild(nodeReg);
       if (next != null) {
-        findStorageGroupPaths(next, nodes, idx + 1,
-            parent + node.getName() + PATH_SEPARATOR, storageGroupPaths);
+        findStorageGroupPaths(node.getChild(nodeReg), nodes, idx + 1,
+            parent + node.getName() + PATH_SEPARATOR, storageGroupPaths, 
prefixOnly);
       }
     } else {
       for (MNode child : node.getChildren().values()) {
         findStorageGroupPaths(
-            child, nodes, idx + 1, parent + node.getName() + PATH_SEPARATOR, 
storageGroupPaths);
+            child, nodes, idx + 1, parent + node.getName() + PATH_SEPARATOR, 
storageGroupPaths,
+            prefixOnly);
       }
     }
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/PartialPath.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/PartialPath.java
index 35dd7be..c5b49e9 100755
--- a/server/src/main/java/org/apache/iotdb/db/metadata/PartialPath.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/PartialPath.java
@@ -50,6 +50,11 @@ public class PartialPath extends Path implements 
Comparable<Path> {
     this.fullPath = path;
   }
 
+  public PartialPath(String device, String measurement) throws 
IllegalPathException {
+    this.fullPath = device + TsFileConstant.PATH_SEPARATOR + measurement;
+    this.nodes = MetaUtils.splitPathToDetachedPath(fullPath);
+  }
+
   /**
    * @param partialNodes nodes of a time series path
    */
@@ -87,6 +92,7 @@ public class PartialPath extends Path implements 
Comparable<Path> {
     int len = nodes.length;
     this.nodes = Arrays.copyOf(nodes, nodes.length + otherNodes.length);
     System.arraycopy(otherNodes, 0, nodes, len, otherNodes.length);
+    fullPath = String.join(TsFileConstant.PATH_SEPARATOR, nodes);
   }
 
   public PartialPath concatNode(String node) {
@@ -99,6 +105,49 @@ public class PartialPath extends Path implements 
Comparable<Path> {
     return nodes;
   }
 
+  public int getNodeLength() {
+    return nodes.length;
+  }
+
+  public String getTailNode() {
+    if (nodes.length <= 0) {
+      return "";
+    }
+    return nodes[nodes.length - 1];
+  }
+
+  /**
+   * Construct a new PartialPath by resetting the prefix nodes to prefixPath
+   * @param prefixPath the prefix path used to replace current nodes
+   * @return A new PartialPath with altered prefix
+   */
+  public PartialPath alterPrefixPath(PartialPath prefixPath) {
+    String[] newNodes = Arrays.copyOf(nodes, Math.max(nodes.length, 
prefixPath.getNodeLength()));
+    System.arraycopy(prefixPath.getNodes(), 0, newNodes, 0, 
prefixPath.getNodeLength());
+    return new PartialPath(newNodes);
+  }
+
+  /**
+   * Test if this PartialPath matches a full path. rPath is supposed to be a 
full timeseries path
+   * without wildcards.
+   * e.g. "root.sg.device.*" matches path "root.sg.device.s1"
+   * whereas it does not match "root.sg.device" and "root.sg.vehicle.s1"
+   * @param rPath a plain full path of a timeseries
+   * @return true if a successful match, otherwise return false
+   */
+  public boolean matchFullPath(PartialPath rPath) {
+    String[] rNodes = rPath.getNodes();
+    if (rNodes.length < nodes.length) {
+      return false;
+    }
+    for (int i = 0; i < nodes.length; i++) {
+      if (!nodes[i].equals(IoTDBConstant.PATH_WILDCARD) && 
!nodes[i].equals(rNodes[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   @Override
   public String getFullPath() {
     if (fullPath != null) {
@@ -167,7 +216,9 @@ public class PartialPath extends Path implements 
Comparable<Path> {
     return measurementAlias;
   }
 
-  public void setMeasurementAlias(String measurementAlias) { 
this.measurementAlias = measurementAlias; }
+  public void setMeasurementAlias(String measurementAlias) {
+    this.measurementAlias = measurementAlias;
+  }
 
   public String getTsAlias() {
     return tsAlias;
diff --git a/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java 
b/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java
index 12cf8f0..41ae412 100644
--- a/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java
@@ -367,7 +367,7 @@ public class StatMonitor implements IService {
         for (Map.Entry<String, IStatistic> entry : statisticMap.entrySet()) {
           for (String statParamName : 
entry.getValue().getStatParamsHashMap().keySet()) {
             if (temporaryStatList.contains(statParamName)) {
-              fManager.delete(new PartialPath(entry.getKey()), statParamName, 
Long.MIN_VALUE,
+              fManager.delete(new PartialPath(entry.getKey(), statParamName), 
Long.MIN_VALUE,
                   currentTimeMillis - statMonitorRetainIntervalSec * 1000);
             }
           }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java 
b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index 5f5b6d6..35fc394 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -710,19 +710,8 @@ public class PlanExecutor implements IPlanExecutor {
 
   @Override
   public void delete(DeletePlan deletePlan) throws QueryProcessException {
-    try {
-      Set<PartialPath> existingPaths = new HashSet<>();
-      for (PartialPath p : deletePlan.getPaths()) {
-        existingPaths.addAll(getPathsName(p));
-      }
-      if (existingPaths.isEmpty()) {
-        throw new QueryProcessException("TimeSeries does not exist and its 
data cannot be deleted");
-      }
-      for (PartialPath path : existingPaths) {
-        delete(path, deletePlan.getDeleteStartTime(), 
deletePlan.getDeleteEndTime());
-      }
-    } catch (MetadataException e) {
-      throw new QueryProcessException(e);
+    for (PartialPath path : deletePlan.getPaths()) {
+      delete(path, deletePlan.getDeleteStartTime(), 
deletePlan.getDeleteEndTime());
     }
   }
 
@@ -893,14 +882,8 @@ public class PlanExecutor implements IPlanExecutor {
 
   @Override
   public void delete(PartialPath path, long startTime, long endTime) throws 
QueryProcessException {
-    PartialPath deviceId = path.getDevicePath();
-    String measurementId = path.getMeasurement();
     try {
-      if (!mManager.isPathExist(path)) {
-        throw new QueryProcessException(
-            String.format("Time series %s does not exist.", 
path.getFullPath()));
-      }
-      StorageEngine.getInstance().delete(deviceId, measurementId, startTime, 
endTime);
+      StorageEngine.getInstance().delete(path, startTime, endTime);
     } catch (StorageEngineException e) {
       throw new QueryProcessException(e);
     }
@@ -1061,7 +1044,7 @@ public class PlanExecutor implements IPlanExecutor {
     try {
       List<String> failedNames = new LinkedList<>();
       for (PartialPath path : deletePathList) {
-        StorageEngine.getInstance().deleteTimeseries(path.getDevicePath(), 
path.getMeasurement());
+        StorageEngine.getInstance().deleteTimeseries(path);
         String failedTimeseries = mManager.deleteTimeseries(path);
         if (!failedTimeseries.isEmpty()) {
           failedNames.add(failedTimeseries);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/context/QueryContext.java 
b/server/src/main/java/org/apache/iotdb/db/query/context/QueryContext.java
index e37d12b..863d4c3 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/context/QueryContext.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/context/QueryContext.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import org.apache.iotdb.db.engine.modification.Modification;
 import org.apache.iotdb.db.engine.modification.ModificationFile;
+import org.apache.iotdb.db.metadata.PartialPath;
 import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
 
 /**
@@ -60,10 +61,10 @@ public class QueryContext {
    * Find the modifications of timeseries 'path' in 'modFile'. If they are not 
in the cache, read
    * them from 'modFile' and put then into the cache.
    */
-  public List<Modification> getPathModifications(ModificationFile modFile, 
String path) {
+  public List<Modification> getPathModifications(ModificationFile modFile, 
PartialPath path) {
     Map<String, List<Modification>> fileModifications =
         filePathModCache.computeIfAbsent(modFile.getFilePath(), k -> new 
ConcurrentHashMap<>());
-    return fileModifications.computeIfAbsent(path, k -> {
+    return fileModifications.computeIfAbsent(path.getFullPath(), k -> {
       List<Modification> allModifications = 
fileModCache.get(modFile.getFilePath());
       if (allModifications == null) {
         allModifications = (List<Modification>) modFile.getModifications();
@@ -72,7 +73,7 @@ public class QueryContext {
       List<Modification> finalPathModifications = new ArrayList<>();
       if (!allModifications.isEmpty()) {
         allModifications.forEach(modification -> {
-          if (modification.getPathString().equals(path)) {
+          if (modification.getPath().matchFullPath(path)) {
             finalPathModifications.add(modification);
           }
         });
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/reader/chunk/metadata/DiskChunkMetadataLoader.java
 
b/server/src/main/java/org/apache/iotdb/db/query/reader/chunk/metadata/DiskChunkMetadataLoader.java
index 20eff72..e196fde 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/reader/chunk/metadata/DiskChunkMetadataLoader.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/reader/chunk/metadata/DiskChunkMetadataLoader.java
@@ -26,7 +26,6 @@ import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.reader.chunk.DiskChunkLoader;
 import org.apache.iotdb.db.utils.QueryUtils;
 import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
-import org.apache.iotdb.tsfile.read.common.Path;
 import org.apache.iotdb.tsfile.read.controller.IChunkMetadataLoader;
 import org.apache.iotdb.tsfile.read.filter.basic.Filter;
 import java.io.IOException;
@@ -71,14 +70,14 @@ public class DiskChunkMetadataLoader implements 
IChunkMetadataLoader {
    * @throws IOException
    */
   @Override
-  public void setDiskChunkLoader(List<ChunkMetadata> chunkMetadataList) throws 
IOException {
+  public void setDiskChunkLoader(List<ChunkMetadata> chunkMetadataList) {
     setDiskChunkLoader(chunkMetadataList, resource, seriesPath, context);
   }
 
   public static void setDiskChunkLoader(List<ChunkMetadata> chunkMetadataList,
-      TsFileResource resource, Path seriesPath, QueryContext context) {
+      TsFileResource resource, PartialPath seriesPath, QueryContext context)  {
     List<Modification> pathModifications =
-        context.getPathModifications(resource.getModFile(), 
seriesPath.getFullPath());
+        context.getPathModifications(resource.getModFile(), seriesPath);
 
     if (!pathModifications.isEmpty()) {
       QueryUtils.modifyChunkMetaData(chunkMetadataList, pathModifications);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/utils/FileLoaderUtils.java 
b/server/src/main/java/org/apache/iotdb/db/utils/FileLoaderUtils.java
index 7f2f520..b3af734 100644
--- a/server/src/main/java/org/apache/iotdb/db/utils/FileLoaderUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/utils/FileLoaderUtils.java
@@ -109,7 +109,7 @@ public class FileLoaderUtils {
 
     if (timeSeriesMetadata != null) {
       List<Modification> pathModifications =
-          context.getPathModifications(resource.getModFile(), 
seriesPath.getFullPath());
+          context.getPathModifications(resource.getModFile(), seriesPath);
       timeSeriesMetadata.setModified(!pathModifications.isEmpty());
       if (timeSeriesMetadata.getStatistics().getStartTime() > 
timeSeriesMetadata.getStatistics()
           .getEndTime()) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/writelog/recover/LogReplayer.java 
b/server/src/main/java/org/apache/iotdb/db/writelog/recover/LogReplayer.java
index 8f9cbd4..d6bf865 100644
--- a/server/src/main/java/org/apache/iotdb/db/writelog/recover/LogReplayer.java
+++ b/server/src/main/java/org/apache/iotdb/db/writelog/recover/LogReplayer.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import org.apache.iotdb.db.engine.memtable.IMemTable;
 import org.apache.iotdb.db.engine.modification.Deletion;
 import org.apache.iotdb.db.engine.modification.ModificationFile;
@@ -117,12 +118,14 @@ public class LogReplayer {
     tempEndTimeMap.forEach((k, v) -> currentTsFileResource.updateEndTime(k, 
v));
   }
 
-  private void replayDelete(DeletePlan deletePlan) throws IOException {
+  private void replayDelete(DeletePlan deletePlan) throws IOException, 
MetadataException {
     List<PartialPath> paths = deletePlan.getPaths();
     for (PartialPath path : paths) {
-      recoverMemTable
-          .delete(path.getDevice(), path.getMeasurement(), 
deletePlan.getDeleteStartTime(),
-              deletePlan.getDeleteEndTime());
+      for (PartialPath device : 
IoTDB.metaManager.getDevices(path.getDevicePath())) {
+        recoverMemTable
+            .delete(path, device, deletePlan.getDeleteStartTime(),
+                deletePlan.getDeleteEndTime());
+      }
       modFile
           .write(
               new Deletion(path, versionController.nextVersion(), 
deletePlan.getDeleteStartTime(),
diff --git 
a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
 
b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
index 5d0ad9e..165fe6d 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
@@ -107,10 +107,10 @@ public class DeletionFileNodeTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 30);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 30, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 30, 50);
 
     SingleSeriesExpression expression = new SingleSeriesExpression(new 
PartialPath(processorName + TsFileConstant.PATH_SEPARATOR +
         measurements[5]), null);
@@ -143,9 +143,9 @@ public class DeletionFileNodeTest {
     }
     StorageEngine.getInstance().syncCloseAllProcessor();
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 40);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 40);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 30);
 
     Modification[] realModifications = new Modification[]{
         new Deletion(new PartialPath(processorName + 
TsFileConstant.PATH_SEPARATOR + measurements[5]), 201, 50),
@@ -207,10 +207,10 @@ public class DeletionFileNodeTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 30);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 30, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 30, 50);
 
     SingleSeriesExpression expression = new SingleSeriesExpression(new 
PartialPath(processorName + TsFileConstant.PATH_SEPARATOR +
         measurements[5]), null);
@@ -256,9 +256,9 @@ public class DeletionFileNodeTest {
     }
     StorageEngine.getInstance().syncCloseAllProcessor();
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 40);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 40);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 30);
 
     Modification[] realModifications = new Modification[]{
         new Deletion(new PartialPath(processorName + 
TsFileConstant.PATH_SEPARATOR + measurements[5]), 301, 50),
diff --git 
a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
 
b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
index be99831..a5b2530 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
@@ -99,10 +99,10 @@ public class DeletionQueryTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 30);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 30, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 30, 50);
 
     List<PartialPath> pathList = new ArrayList<>();
     pathList.add(new PartialPath(processorName + TsFileConstant.PATH_SEPARATOR 
+ measurements[3]));
@@ -138,9 +138,9 @@ public class DeletionQueryTest {
     }
     StorageEngine.getInstance().syncCloseAllProcessor();
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 40);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 40);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 30);
 
     List<PartialPath> pathList = new ArrayList<>();
     pathList.add(new PartialPath(processorName + TsFileConstant.PATH_SEPARATOR 
+ measurements[3]));
@@ -187,10 +187,10 @@ public class DeletionQueryTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 30);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 30, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 30, 50);
 
     List<PartialPath> pathList = new ArrayList<>();
     pathList.add(new PartialPath(processorName + TsFileConstant.PATH_SEPARATOR 
+ measurements[3]));
@@ -237,9 +237,9 @@ public class DeletionQueryTest {
     }
     StorageEngine.getInstance().syncCloseAllProcessor();
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 40);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 40);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 30);
 
     List<PartialPath> pathList = new ArrayList<>();
     pathList.add(new PartialPath(processorName + TsFileConstant.PATH_SEPARATOR 
+ measurements[3]));
@@ -275,10 +275,10 @@ public class DeletionQueryTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 30);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 30, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 30, 50);
 
     StorageEngine.getInstance().syncCloseAllProcessor();
 
@@ -290,10 +290,10 @@ public class DeletionQueryTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 250);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 250);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 230);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 230, 250);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 250);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 250);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 230);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 230, 250);
 
     StorageEngine.getInstance().syncCloseAllProcessor();
 
@@ -305,10 +305,10 @@ public class DeletionQueryTest {
       insertToStorageEngine(record);
     }
 
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[3], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[4], 0, 50);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 0, 30);
-    StorageEngine.getInstance().delete(new PartialPath(processorName), 
measurements[5], 30, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[3]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[4]), 0, 50);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 0, 30);
+    StorageEngine.getInstance().delete(new PartialPath(processorName, 
measurements[5]), 30, 50);
 
     StorageEngine.getInstance().syncCloseAllProcessor();
 
diff --git 
a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
 
b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
index cfa7c64..bb649b0 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
@@ -39,6 +39,7 @@ import 
org.apache.iotdb.db.engine.tsfilemanagement.TsFileManagementStrategy;
 import org.apache.iotdb.db.exception.StorageGroupProcessorException;
 import org.apache.iotdb.db.exception.WriteProcessException;
 import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.PartialPath;
 import org.apache.iotdb.db.metadata.mnode.MeasurementMNode;
@@ -98,7 +99,7 @@ public class StorageGroupProcessorTest {
 
   @Test
   public void testUnseqUnsealedDelete()
-      throws WriteProcessException, IOException, IllegalPathException {
+      throws WriteProcessException, IOException, MetadataException {
     TSRecord record = new TSRecord(10000, deviceId);
     record.addTuple(DataPoint.getDataPoint(TSDataType.INT32, measurementId, 
String.valueOf(1000)));
     insertToStorageGroupProcessor(record);
@@ -120,7 +121,7 @@ public class StorageGroupProcessorTest {
       insertToStorageGroupProcessor(record);
     }
 
-    processor.delete(new PartialPath(deviceId), measurementId, 0, 15L);
+    processor.delete(new PartialPath(deviceId, measurementId), 0, 15L);
 
     List<TsFileResource> tsfileResourcesForQuery = new ArrayList<>();
     for (TsFileProcessor tsfileProcessor : 
processor.getWorkUnsequenceTsFileProcessor()) {
diff --git 
a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
 
b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
index adaf93c..f3d3f0b 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
@@ -37,6 +37,7 @@ import 
org.apache.iotdb.db.engine.version.SysTimeVersionController;
 import org.apache.iotdb.db.exception.TsFileProcessorException;
 import org.apache.iotdb.db.exception.WriteProcessException;
 import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
@@ -83,7 +84,7 @@ public class TsFileProcessorTest {
   }
 
   @Test
-  public void testWriteAndFlush() throws IOException, WriteProcessException, 
IllegalPathException {
+  public void testWriteAndFlush() throws IOException, WriteProcessException, 
MetadataException {
     logger.info("testWriteAndFlush begin..");
     processor = new TsFileProcessor(storageGroup, 
SystemFileFactory.INSTANCE.getFile(filePath),
         SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
@@ -134,7 +135,7 @@ public class TsFileProcessorTest {
 
   @Test
   public void testWriteAndRestoreMetadata()
-      throws IOException, WriteProcessException, IllegalPathException {
+      throws IOException, WriteProcessException, MetadataException {
     logger.info("testWriteAndRestoreMetadata begin..");
     processor = new TsFileProcessor(storageGroup, 
SystemFileFactory.INSTANCE.getFile(filePath),
         SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
@@ -211,7 +212,7 @@ public class TsFileProcessorTest {
 
 
   @Test
-  public void testMultiFlush() throws IOException, WriteProcessException, 
IllegalPathException {
+  public void testMultiFlush() throws IOException, WriteProcessException, 
MetadataException {
     logger.info("testWriteAndRestoreMetadata begin..");
     processor = new TsFileProcessor(storageGroup, 
SystemFileFactory.INSTANCE.getFile(filePath),
         SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
@@ -246,7 +247,7 @@ public class TsFileProcessorTest {
   }
 
   @Test
-  public void testWriteAndClose() throws IOException, WriteProcessException, 
IllegalPathException {
+  public void testWriteAndClose() throws IOException, WriteProcessException, 
MetadataException {
     logger.info("testWriteAndRestoreMetadata begin..");
     processor = new TsFileProcessor(storageGroup, 
SystemFileFactory.INSTANCE.getFile(filePath),
         SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java 
b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
index c5af5c4..fd5db9c 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.apache.iotdb.db.exception.metadata.AliasAlreadyExistException;
@@ -475,4 +476,24 @@ public class MTreeTest {
           e.getMessage());
     }
   }
+
+  @Test
+  public void testSearchStorageGroup() throws MetadataException {
+    MTree root = new MTree();
+    String path1 = "root";
+    String sgPath1 = "root.vehicle";
+    root.setStorageGroup(new PartialPath(sgPath1));
+    assertTrue(root.isPathExist(new PartialPath(path1)));
+    try {
+      root.createTimeseries(new PartialPath("root.vehicle.d1.s1"), 
TSDataType.INT32, TSEncoding.RLE,
+          TSFileDescriptor.getInstance().getConfig().getCompressor(), 
Collections.emptyMap(), null);
+      root.createTimeseries(new PartialPath("root.vehicle.d1.s2"), 
TSDataType.INT32, TSEncoding.RLE,
+          TSFileDescriptor.getInstance().getConfig().getCompressor(), 
Collections.emptyMap(), null);
+    } catch (MetadataException e1) {
+      fail(e1.getMessage());
+    }
+
+    assertEquals(root.searchAllRelatedStorageGroups(new 
PartialPath("root.vehicle.d1.s1")),
+        Arrays.asList(new PartialPath(sgPath1)));
+  }
 }
diff --git 
a/server/src/test/java/org/apache/iotdb/db/metadata/PartialPathTest.java 
b/server/src/test/java/org/apache/iotdb/db/metadata/PartialPathTest.java
index fb02d6f..4b77d44 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/PartialPathTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/PartialPathTest.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.db.metadata;
 
 import java.util.Arrays;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.junit.After;
 import org.junit.Assert;
@@ -68,7 +69,31 @@ public class PartialPathTest {
     arr1[0] = "root";
     arr1[1] = "sg1";
     PartialPath a = new PartialPath(arr1);
-    Assert.assertEquals("[root, sg1, d1]", 
Arrays.toString(a.concatNode("d1").getNodes()));
+    String[] arr2 = new String[1];
+    arr2[0] = "d1";
+    a.concatPath(arr2);
+    Assert.assertEquals("[root, sg1, d1]", Arrays.toString(a.getNodes()));
+    Assert.assertEquals("root.sg1.d1", a.getFullPath());
+  }
+
+  @Test
+  public void testAlterPrefixPath() throws IllegalPathException {
+    PartialPath p1 = new PartialPath("root.sg1.d1.s1");
+    PartialPath p2 = p1.alterPrefixPath(new PartialPath("root.sg2"));
+    PartialPath p3 = p1.alterPrefixPath(new PartialPath("root.sg2.d1.d2.s3"));
+
+    Assert.assertEquals("root.sg2.d1.s1", p2.getFullPath());
+    Assert.assertEquals("root.sg2.d1.d2.s3", p3.getFullPath());
+  }
+
+  @Test
+  public void testMatchPath() throws IllegalPathException {
+    PartialPath p1 = new PartialPath("root.sg1.d1.*");
+
+    Assert.assertTrue(p1.matchFullPath(new PartialPath("root.sg1.d1.s2")));
+    Assert.assertFalse(p1.matchFullPath(new PartialPath("root.sg1.d1")));
+    Assert.assertFalse(p1.matchFullPath(new PartialPath("root.sg2.d1.*")));
+    Assert.assertFalse(p1.matchFullPath(new PartialPath("")));
   }
 
 }

Reply via email to