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

jackietien pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/dev/1.3 by this push:
     new 658c2672d34 [To dev/1.3] Optimize query execution in easy query case 
(#15128)
658c2672d34 is described below

commit 658c2672d3498a484f13f46f24a3a93b8a2b83fa
Author: Jackie Tien <[email protected]>
AuthorDate: Wed Mar 19 17:13:17 2025 +0800

    [To dev/1.3] Optimize query execution in easy query case (#15128)
---
 .../fragment/FragmentInstanceContext.java          | 39 +++++++++++------
 .../dataregion/VirtualDataRegion.java              |  2 +-
 .../dataregion/tsfile/TsFileResource.java          | 49 ++++++++++++----------
 .../tsfile/timeindex/DeviceTimeIndex.java          | 12 ++++--
 4 files changed, 62 insertions(+), 40 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
index 5b1600710e9..58f06bfb270 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.queryengine.execution.fragment;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.commons.path.AlignedPath;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
@@ -49,7 +50,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.time.ZoneId;
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -60,6 +60,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
+import static 
org.apache.iotdb.db.storageengine.dataregion.VirtualDataRegion.EMPTY_QUERY_DATA_SOURCE;
+
 public class FragmentInstanceContext extends QueryContext {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(FragmentInstanceContext.class);
@@ -416,24 +418,37 @@ public class FragmentInstanceContext extends QueryContext 
{
 
   public void initQueryDataSource(List<PartialPath> sourcePaths) throws 
QueryProcessException {
     long startTime = System.nanoTime();
-    if (sourcePaths == null) {
+    if (sourcePaths == null || sourcePaths.isEmpty()) {
+      this.sharedQueryDataSource = EMPTY_QUERY_DATA_SOURCE;
       return;
     }
+    String singleDevice = null;
+    if (sourcePaths.size() == 1) {
+      singleDevice = sourcePaths.get(0).getDevice();
+    } else {
+      Set<String> selectedDeviceSet = new HashSet<>();
+      for (PartialPath sourcePath : sourcePaths) {
+        if (sourcePath instanceof AlignedPath) {
+          singleDevice = null;
+          break;
+        } else {
+          singleDevice = sourcePath.getDevice();
+          selectedDeviceSet.add(singleDevice);
+          if (selectedDeviceSet.size() > 1) {
+            singleDevice = null;
+            break;
+          }
+        }
+      }
+    }
     dataRegion.readLock();
     try {
-      List<PartialPath> pathList = new ArrayList<>();
-      Set<String> selectedDeviceIdSet = new HashSet<>();
-      for (PartialPath path : sourcePaths) {
-        pathList.add(path);
-        selectedDeviceIdSet.add(path.getDevice());
-      }
-
       this.sharedQueryDataSource =
           dataRegion.query(
-              pathList,
+              sourcePaths,
               // when all the selected series are under the same device, the 
QueryDataSource will be
               // filtered according to timeIndex
-              selectedDeviceIdSet.size() == 1 ? 
selectedDeviceIdSet.iterator().next() : null,
+              singleDevice,
               this,
               // time filter may be stateful, so we need to copy it
               globalTimeFilter != null ? globalTimeFilter.copy() : null,
@@ -445,7 +460,7 @@ public class FragmentInstanceContext extends QueryContext {
         closedFilePaths = new HashSet<>();
         unClosedFilePaths = new HashSet<>();
         addUsedFilesForQuery((QueryDataSource) sharedQueryDataSource);
-        ((QueryDataSource) 
sharedQueryDataSource).setSingleDevice(selectedDeviceIdSet.size() == 1);
+        ((QueryDataSource) sharedQueryDataSource).setSingleDevice(singleDevice 
!= null);
       }
     } finally {
       setInitQueryDataSourceCost(System.nanoTime() - startTime);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/VirtualDataRegion.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/VirtualDataRegion.java
index 42c5a766886..c71111324c4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/VirtualDataRegion.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/VirtualDataRegion.java
@@ -41,7 +41,7 @@ public class VirtualDataRegion implements IDataRegionForQuery 
{
 
   private static final String VIRTUAL_DB_NAME = "root.__virtual";
 
-  private static final QueryDataSource EMPTY_QUERY_DATA_SOURCE =
+  public static final QueryDataSource EMPTY_QUERY_DATA_SOURCE =
       new QueryDataSource(Collections.emptyList(), Collections.emptyList());
 
   private static final QueryDataSourceForRegionScan 
EMPTY_REGION_QUERY_DATA_SOURCE =
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java
index e0e958a6b1a..9525b57e75b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java
@@ -461,10 +461,10 @@ public class TsFileResource {
 
   // cannot use FileTimeIndex
   public long getOrderTimeForSeq(IDeviceID deviceId, boolean ascending) {
-    if (timeIndex instanceof DeviceTimeIndex && 
!definitelyNotContains(deviceId)) {
-      // checked above
-      //noinspection OptionalGetWithoutIsPresent
-      return ascending ? getStartTime(deviceId).get() : 
getEndTime(deviceId).get();
+    if (timeIndex instanceof DeviceTimeIndex) {
+      return ascending
+          ? timeIndex.getStartTime(deviceId).orElse(Long.MIN_VALUE)
+          : timeIndex.getEndTime(deviceId).orElse(Long.MAX_VALUE);
     } else {
       return ascending ? Long.MIN_VALUE : Long.MAX_VALUE;
     }
@@ -472,12 +472,15 @@ public class TsFileResource {
 
   // can use FileTimeIndex
   public long getOrderTimeForUnseq(IDeviceID deviceId, boolean ascending) {
-    if (!definitelyNotContains(deviceId)) {
-      // checked above
-      //noinspection OptionalGetWithoutIsPresent
-      return ascending ? getStartTime(deviceId).get() : 
getEndTime(deviceId).get();
+    if (timeIndex instanceof DeviceTimeIndex) {
+      if (ascending) {
+        return timeIndex.getStartTime(deviceId).orElse(Long.MIN_VALUE);
+      } else {
+        return timeIndex.getEndTime(deviceId).orElse(Long.MAX_VALUE);
+      }
     } else {
-      return ascending ? Long.MIN_VALUE : Long.MAX_VALUE;
+      // FileTimeIndex
+      return ascending ? getFileStartTime() : getFileEndTime();
     }
   }
 
@@ -814,21 +817,21 @@ public class TsFileResource {
       return false;
     }
 
-    // check above
-    long startTime = getStartTime(deviceId).get();
-    long endTime = isClosed() || !isSeq ? getEndTime(deviceId).get() : 
Long.MAX_VALUE;
-    if (startTime > endTime) {
-      // startTime > endTime indicates that there is something wrong with this 
TsFile. Return false
-      // directly, or it may lead to infinite loop in 
GroupByMonthFilter#getTimePointPosition.
-      LOGGER.warn(
-          "startTime[{}] of TsFileResource[{}] is greater than its 
endTime[{}]",
-          startTime,
-          this,
-          endTime);
-      return false;
-    }
-
     if (timeFilter != null) {
+      // check above
+      long startTime = getStartTime(deviceId).get();
+      long endTime = isClosed() || !isSeq ? getEndTime(deviceId).get() : 
Long.MAX_VALUE;
+      if (startTime > endTime) {
+        // startTime > endTime indicates that there is something wrong with 
this TsFile. Return
+        // false
+        // directly, or it may lead to infinite loop in 
GroupByMonthFilter#getTimePointPosition.
+        LOGGER.warn(
+            "startTime[{}] of TsFileResource[{}] is greater than its 
endTime[{}]",
+            startTime,
+            this,
+            endTime);
+        return false;
+      }
       boolean res = timeFilter.satisfyStartEndTime(startTime, endTime);
       if (debug && !res) {
         DEBUG_LOGGER.info(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/DeviceTimeIndex.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/DeviceTimeIndex.java
index 75f6739074f..cc2e100a71d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/DeviceTimeIndex.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/DeviceTimeIndex.java
@@ -349,18 +349,22 @@ public class DeviceTimeIndex implements ITimeIndex {
 
   @Override
   public Optional<Long> getStartTime(IDeviceID deviceId) {
-    if (!deviceToIndex.containsKey(deviceId)) {
+    Integer index = deviceToIndex.get(deviceId);
+    if (index == null) {
       return Optional.empty();
+    } else {
+      return Optional.of(startTimes[index]);
     }
-    return Optional.of(startTimes[deviceToIndex.get(deviceId)]);
   }
 
   @Override
   public Optional<Long> getEndTime(IDeviceID deviceId) {
-    if (!deviceToIndex.containsKey(deviceId)) {
+    Integer index = deviceToIndex.get(deviceId);
+    if (index == null) {
       return Optional.empty();
+    } else {
+      return Optional.of(endTimes[index]);
     }
-    return Optional.of(endTimes[deviceToIndex.get(deviceId)]);
   }
 
   @Override

Reply via email to