You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ja...@apache.org on 2024/10/29 18:46:18 UTC
(pinot) branch master updated: Add minor optimization for FIRST_VALUE / LAST_VALUE with IGNORE NULLS and unbounded ROWS window frame (#14324)
This is an automated email from the ASF dual-hosted git repository.
jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 4bafac8439 Add minor optimization for FIRST_VALUE / LAST_VALUE with IGNORE NULLS and unbounded ROWS window frame (#14324)
4bafac8439 is described below
commit 4bafac8439e006750308ad8031c373791c594b1c
Author: Yash Mayya <ya...@gmail.com>
AuthorDate: Wed Oct 30 00:16:13 2024 +0530
Add minor optimization for FIRST_VALUE / LAST_VALUE with IGNORE NULLS and unbounded ROWS window frame (#14324)
---
.../window/value/FirstValueWindowFunction.java | 35 ++++++++++++++--------
.../window/value/LastValueWindowFunction.java | 29 +++++++++++-------
.../operator/window/value/ValueWindowFunction.java | 7 -----
3 files changed, 42 insertions(+), 29 deletions(-)
diff --git a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
index a1f84be32e..7baebe8b41 100644
--- a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
+++ b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
@@ -58,11 +58,12 @@ public class FirstValueWindowFunction extends ValueWindowFunction {
}
private List<Object> processRowsWindow(List<Object[]> rows) {
+ int numRows = rows.size();
+
if (_windowFrame.isUnboundedPreceding() && _windowFrame.getUpperBound() >= 0) {
- return fillAllWithValue(rows, extractValueFromRow(rows.get(0)));
+ return Collections.nCopies(numRows, extractValueFromRow(rows.get(0)));
}
- int numRows = rows.size();
List<Object> result = new ArrayList<>(numRows);
// lowerBound is guaranteed to be less than or equal to upperBound here (but both can be -ve / +ve)
@@ -92,6 +93,10 @@ public class FirstValueWindowFunction extends ValueWindowFunction {
}
private List<Object> processRowsWindowIgnoreNulls(List<Object[]> rows) {
+ if (_windowFrame.isUnboundedPreceding() && _windowFrame.isUnboundedFollowing()) {
+ return processUnboundedWindowIgnoreNulls(rows);
+ }
+
int numRows = rows.size();
int lowerBound = _windowFrame.getLowerBound();
int upperBound = Math.min(_windowFrame.getUpperBound(), numRows - 1);
@@ -143,15 +148,16 @@ public class FirstValueWindowFunction extends ValueWindowFunction {
}
private List<Object> processRangeWindow(List<Object[]> rows) {
+ int numRows = rows.size();
+
if (_windowFrame.isUnboundedPreceding()) {
- return fillAllWithValue(rows, extractValueFromRow(rows.get(0)));
+ return Collections.nCopies(numRows, extractValueFromRow(rows.get(0)));
}
// The lower bound has to be CURRENT ROW since we don't support RANGE windows with offset value
Preconditions.checkState(_windowFrame.isLowerBoundCurrentRow(),
"RANGE window frame with offset PRECEDING / FOLLOWING is not supported");
- int numRows = rows.size();
List<Object> result = new ArrayList<>(numRows);
// The window frame here is either RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING or RANGE BETWEEN CURRENT ROW
@@ -178,14 +184,7 @@ public class FirstValueWindowFunction extends ValueWindowFunction {
int numRows = rows.size();
if (_windowFrame.isUnboundedPreceding() && _windowFrame.isUnboundedFollowing()) {
- // Find the first non-null value and fill it in all rows
- int indexOfFirstNonNullValue = indexOfFirstNonNullValueInWindow(rows, 0, numRows - 1);
- if (indexOfFirstNonNullValue == -1) {
- // There's no non-null value
- return Collections.nCopies(numRows, null);
- } else {
- return fillAllWithValue(rows, extractValueFromRow(rows.get(indexOfFirstNonNullValue)));
- }
+ return processUnboundedWindowIgnoreNulls(rows);
}
if (_windowFrame.isUnboundedPreceding() && _windowFrame.isUpperBoundCurrentRow()) {
@@ -270,6 +269,18 @@ public class FirstValueWindowFunction extends ValueWindowFunction {
throw new IllegalStateException("RANGE window frame with offset PRECEDING / FOLLOWING is not supported");
}
+ private List<Object> processUnboundedWindowIgnoreNulls(List<Object[]> rows) {
+ int numRows = rows.size();
+ // Find the first non-null value and fill it in all rows
+ int indexOfFirstNonNullValue = indexOfFirstNonNullValueInWindow(rows, 0, numRows - 1);
+ if (indexOfFirstNonNullValue == -1) {
+ // There's no non-null value
+ return Collections.nCopies(numRows, null);
+ } else {
+ return Collections.nCopies(numRows, extractValueFromRow(rows.get(indexOfFirstNonNullValue)));
+ }
+ }
+
/**
* Both lowerBound and upperBound should be valid values for the given row set. The returned value is -1 if there is
* no non-null value in the window.
diff --git a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
index 5383525d2d..8da5fa6fb1 100644
--- a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
+++ b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
@@ -60,7 +60,7 @@ public class LastValueWindowFunction extends ValueWindowFunction {
private List<Object> processRowsWindow(List<Object[]> rows) {
int numRows = rows.size();
if (_windowFrame.isUnboundedFollowing() && _windowFrame.getLowerBound() <= 0) {
- return fillAllWithValue(rows, extractValueFromRow(rows.get(numRows - 1)));
+ return Collections.nCopies(numRows, extractValueFromRow(rows.get(numRows - 1)));
}
List<Object> result = new ArrayList<>(numRows);
@@ -92,6 +92,10 @@ public class LastValueWindowFunction extends ValueWindowFunction {
}
private List<Object> processRowsWindowIgnoreNulls(List<Object[]> rows) {
+ if (_windowFrame.isUnboundedPreceding() && _windowFrame.isUnboundedFollowing()) {
+ return processUnboundedWindowIgnoreNulls(rows);
+ }
+
int numRows = rows.size();
int lowerBound = _windowFrame.getLowerBound();
int upperBound = Math.min(_windowFrame.getUpperBound(), numRows - 1);
@@ -142,7 +146,7 @@ public class LastValueWindowFunction extends ValueWindowFunction {
private List<Object> processRangeWindow(List<Object[]> rows) {
int numRows = rows.size();
if (_windowFrame.isUnboundedFollowing()) {
- return fillAllWithValue(rows, extractValueFromRow(rows.get(numRows - 1)));
+ return Collections.nCopies(numRows, extractValueFromRow(rows.get(numRows - 1)));
}
// The upper bound has to be CURRENT ROW here since we don't support RANGE windows with offset value
@@ -177,14 +181,7 @@ public class LastValueWindowFunction extends ValueWindowFunction {
int numRows = rows.size();
if (_windowFrame.isUnboundedPreceding() && _windowFrame.isUnboundedFollowing()) {
- // Find the last non-null value and fill it in all rows
- int indexOfLastNonNullValue = indexOfLastNonNullValueInWindow(rows, 0, numRows - 1);
- if (indexOfLastNonNullValue == -1) {
- // There's no non-null value
- return Collections.nCopies(numRows, null);
- } else {
- return fillAllWithValue(rows, extractValueFromRow(rows.get(indexOfLastNonNullValue)));
- }
+ return processUnboundedWindowIgnoreNulls(rows);
}
if (_windowFrame.isUnboundedPreceding() && _windowFrame.isUpperBoundCurrentRow()) {
@@ -259,6 +256,18 @@ public class LastValueWindowFunction extends ValueWindowFunction {
throw new IllegalStateException("RANGE window frame with offset PRECEDING / FOLLOWING is not supported");
}
+ private List<Object> processUnboundedWindowIgnoreNulls(List<Object[]> rows) {
+ int numRows = rows.size();
+ // Find the last non-null value and fill it in all rows
+ int indexOfLastNonNullValue = indexOfLastNonNullValueInWindow(rows, 0, numRows - 1);
+ if (indexOfLastNonNullValue == -1) {
+ // There's no non-null value
+ return Collections.nCopies(numRows, null);
+ } else {
+ return Collections.nCopies(numRows, extractValueFromRow(rows.get(indexOfLastNonNullValue)));
+ }
+ }
+
/**
* Both lowerBound and upperBound should be valid values for the given row set. The returned value is -1 if there is
* no non-null value in the window.
diff --git a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
index ce8a00d432..154c846766 100644
--- a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
+++ b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
@@ -19,7 +19,6 @@
package org.apache.pinot.query.runtime.operator.window.value;
import com.google.common.collect.ImmutableMap;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.calcite.rel.RelFieldCollation;
@@ -48,10 +47,4 @@ public abstract class ValueWindowFunction extends WindowFunction {
super(aggCall, inputSchema, collations, windowFrame);
_ignoreNulls = aggCall.isIgnoreNulls();
}
-
- protected List<Object> fillAllWithValue(List<Object[]> rows, Object value) {
- int numRows = rows.size();
- assert numRows > 0;
- return Collections.nCopies(numRows, value);
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org