This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch OptQueryExec-1.3 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 63f5970664c1a246d8de2a7c39442ddb9681b419 Author: JackieTien97 <[email protected]> AuthorDate: Wed Mar 19 09:56:29 2025 +0800 Optimize query execution in easy query case --- .../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
