JackieTien97 commented on code in PR #10890:
URL: https://github.com/apache/iotdb/pull/10890#discussion_r1299552367
##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/optimization/LimitOffsetPushDown.java:
##########
@@ -239,4 +248,116 @@ public Analysis getAnalysis() {
return analysis;
}
}
+
+ // following methods are used to push down limit/offset in group by time
+
+ // 1. push down limit/offset to group by time in align by time
+
+ public static boolean canPushDownLimitOffsetToGroupByTime(QueryStatement
queryStatement) {
+ if (queryStatement.isGroupByTime()
+ && !queryStatement.isAlignByDevice()
+ && !queryStatement.hasHaving()
+ && !queryStatement.hasFill()) {
+ return !queryStatement.hasOrderBy() ||
queryStatement.isOrderByBasedOnTime();
+ }
+ return false;
+ }
+
+ public static void pushDownLimitOffsetToTimeParameter(QueryStatement
queryStatement) {
+ GroupByTimeComponent groupByTimeComponent =
queryStatement.getGroupByTimeComponent();
+ long startTime = groupByTimeComponent.getStartTime();
+ long endTime = groupByTimeComponent.getEndTime();
+ long step = groupByTimeComponent.getSlidingStep();
+ long interval = groupByTimeComponent.getInterval();
+
+ long size = (long) Math.ceil((endTime - startTime) / (double) step);
+ if (size > queryStatement.getRowOffset()) {
+ long limitSize = queryStatement.getRowLimit();
+ long offsetSize = queryStatement.getRowOffset();
+ if (queryStatement.getResultTimeOrder() == Ordering.ASC) {
+ startTime = startTime + offsetSize * step;
+ } else {
+ startTime = startTime + (size - offsetSize - limitSize) * step;
+ }
+ endTime =
+ limitSize == 0
+ ? endTime
+ : Math.min(endTime, startTime + (limitSize - 1) * step +
interval);
+ groupByTimeComponent.setEndTime(endTime);
+ groupByTimeComponent.setStartTime(startTime);
+ } else {
+ // finish the query, resultSet is empty
+ queryStatement.setFromComponent(new FromComponent());
+ }
+ queryStatement.setRowLimit(0);
+ queryStatement.setRowOffset(0);
+ }
+
+ // 2. push down limit/offset to group by time in align by device
+ public static boolean canPushDownLimitOffsetInGroupByTimeForDevice(
+ QueryStatement queryStatement) {
+ if (!hasLimitOffset(queryStatement)) {
+ return false;
+ }
+
+ if (queryStatement.isGroupByTime()
+ && queryStatement.isAlignByDevice()
+ && !queryStatement.hasHaving()
+ && !queryStatement.hasFill()) {
+ return !queryStatement.hasOrderBy() ||
queryStatement.isOrderByBasedOnDevice();
+ }
+ return false;
+ }
+
+ public static Set<PartialPath> pushDownLimitOffsetInGroupByTimeForDevice(
+ Set<PartialPath> deviceNames, QueryStatement queryStatement) {
+ GroupByTimeComponent groupByTimeComponent =
queryStatement.getGroupByTimeComponent();
+ long startTime = groupByTimeComponent.getStartTime();
+ long endTime = groupByTimeComponent.getEndTime();
+
+ long size =
+ (long) Math.ceil((endTime - startTime) / (double)
groupByTimeComponent.getSlidingStep());
Review Comment:
```suggestion
long size = (endTime - startTime + groupByTimeComponent.getSlidingStep()
-1 ) / groupByTimeComponent.getSlidingStep();
```
##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analysis.java:
##########
@@ -127,6 +127,9 @@ aggregation results last_value(temperature) and
last_value(status), whereas buck
// Query Analysis (used in ALIGN BY DEVICE)
/////////////////////////////////////////////////////////////////////////////////////////////////
+ // the list of device names
+ private Set<PartialPath> deviceSet;
Review Comment:
```suggestion
private List<PartialPath> deviceSet;
```
##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/optimization/LimitOffsetPushDown.java:
##########
@@ -239,4 +248,116 @@ public Analysis getAnalysis() {
return analysis;
}
}
+
+ // following methods are used to push down limit/offset in group by time
+
+ // 1. push down limit/offset to group by time in align by time
+
+ public static boolean canPushDownLimitOffsetToGroupByTime(QueryStatement
queryStatement) {
+ if (queryStatement.isGroupByTime()
+ && !queryStatement.isAlignByDevice()
+ && !queryStatement.hasHaving()
+ && !queryStatement.hasFill()) {
+ return !queryStatement.hasOrderBy() ||
queryStatement.isOrderByBasedOnTime();
+ }
+ return false;
+ }
+
+ public static void pushDownLimitOffsetToTimeParameter(QueryStatement
queryStatement) {
+ GroupByTimeComponent groupByTimeComponent =
queryStatement.getGroupByTimeComponent();
+ long startTime = groupByTimeComponent.getStartTime();
+ long endTime = groupByTimeComponent.getEndTime();
+ long step = groupByTimeComponent.getSlidingStep();
+ long interval = groupByTimeComponent.getInterval();
+
+ long size = (long) Math.ceil((endTime - startTime) / (double) step);
+ if (size > queryStatement.getRowOffset()) {
+ long limitSize = queryStatement.getRowLimit();
+ long offsetSize = queryStatement.getRowOffset();
+ if (queryStatement.getResultTimeOrder() == Ordering.ASC) {
+ startTime = startTime + offsetSize * step;
+ } else {
+ startTime = startTime + (size - offsetSize - limitSize) * step;
+ }
+ endTime =
+ limitSize == 0
+ ? endTime
+ : Math.min(endTime, startTime + (limitSize - 1) * step +
interval);
+ groupByTimeComponent.setEndTime(endTime);
+ groupByTimeComponent.setStartTime(startTime);
+ } else {
+ // finish the query, resultSet is empty
+ queryStatement.setFromComponent(new FromComponent());
+ }
+ queryStatement.setRowLimit(0);
+ queryStatement.setRowOffset(0);
+ }
+
+ // 2. push down limit/offset to group by time in align by device
+ public static boolean canPushDownLimitOffsetInGroupByTimeForDevice(
+ QueryStatement queryStatement) {
+ if (!hasLimitOffset(queryStatement)) {
+ return false;
+ }
+
+ if (queryStatement.isGroupByTime()
+ && queryStatement.isAlignByDevice()
+ && !queryStatement.hasHaving()
+ && !queryStatement.hasFill()) {
+ return !queryStatement.hasOrderBy() ||
queryStatement.isOrderByBasedOnDevice();
+ }
+ return false;
+ }
+
+ public static Set<PartialPath> pushDownLimitOffsetInGroupByTimeForDevice(
+ Set<PartialPath> deviceNames, QueryStatement queryStatement) {
+ GroupByTimeComponent groupByTimeComponent =
queryStatement.getGroupByTimeComponent();
+ long startTime = groupByTimeComponent.getStartTime();
+ long endTime = groupByTimeComponent.getEndTime();
+
+ long size =
+ (long) Math.ceil((endTime - startTime) / (double)
groupByTimeComponent.getSlidingStep());
+ if (size == 0 || size * deviceNames.size() <=
queryStatement.getRowOffset()) {
+ // resultSet is empty
+ return Collections.emptySet();
+ }
+
+ long limitSize = queryStatement.getRowLimit();
+ long offsetSize = queryStatement.getRowOffset();
+ Set<PartialPath> optimizedDeviceNames = new LinkedHashSet<>();
Review Comment:
No need to be a `Set`, `List` is enough.
##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/optimization/LimitOffsetPushDown.java:
##########
@@ -239,4 +248,116 @@ public Analysis getAnalysis() {
return analysis;
}
}
+
+ // following methods are used to push down limit/offset in group by time
+
+ // 1. push down limit/offset to group by time in align by time
+
+ public static boolean canPushDownLimitOffsetToGroupByTime(QueryStatement
queryStatement) {
+ if (queryStatement.isGroupByTime()
+ && !queryStatement.isAlignByDevice()
+ && !queryStatement.hasHaving()
+ && !queryStatement.hasFill()) {
+ return !queryStatement.hasOrderBy() ||
queryStatement.isOrderByBasedOnTime();
+ }
+ return false;
+ }
+
+ public static void pushDownLimitOffsetToTimeParameter(QueryStatement
queryStatement) {
+ GroupByTimeComponent groupByTimeComponent =
queryStatement.getGroupByTimeComponent();
+ long startTime = groupByTimeComponent.getStartTime();
+ long endTime = groupByTimeComponent.getEndTime();
+ long step = groupByTimeComponent.getSlidingStep();
+ long interval = groupByTimeComponent.getInterval();
+
+ long size = (long) Math.ceil((endTime - startTime) / (double) step);
Review Comment:
```suggestion
long size = (endTime - startTime + step - 1) / step;
```
##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/optimization/LimitOffsetPushDown.java:
##########
@@ -239,4 +248,116 @@ public Analysis getAnalysis() {
return analysis;
}
}
+
+ // following methods are used to push down limit/offset in group by time
+
+ // 1. push down limit/offset to group by time in align by time
+
+ public static boolean canPushDownLimitOffsetToGroupByTime(QueryStatement
queryStatement) {
+ if (queryStatement.isGroupByTime()
+ && !queryStatement.isAlignByDevice()
+ && !queryStatement.hasHaving()
+ && !queryStatement.hasFill()) {
+ return !queryStatement.hasOrderBy() ||
queryStatement.isOrderByBasedOnTime();
+ }
+ return false;
+ }
+
+ public static void pushDownLimitOffsetToTimeParameter(QueryStatement
queryStatement) {
+ GroupByTimeComponent groupByTimeComponent =
queryStatement.getGroupByTimeComponent();
+ long startTime = groupByTimeComponent.getStartTime();
+ long endTime = groupByTimeComponent.getEndTime();
+ long step = groupByTimeComponent.getSlidingStep();
+ long interval = groupByTimeComponent.getInterval();
+
+ long size = (long) Math.ceil((endTime - startTime) / (double) step);
Review Comment:
Avoid using double cast, this may not be precise
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]