提交 d902164b authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Optimize window aggregates with AND UNBOUNDED FOLLOWING and no exclusions

上级 fe26f354
...@@ -98,15 +98,22 @@ public abstract class AbstractAggregate extends DataAnalysisOperation { ...@@ -98,15 +98,22 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
aggregateFastPartition(session, result, ordered, rowIdColumn, grouped); aggregateFastPartition(session, result, ordered, rowIdColumn, grouped);
return; return;
} }
if (frame.getStarting().getType() == WindowFrameBoundType.UNBOUNDED_PRECEDING if (frame.getExclusion() == WindowFrameExclusion.EXCLUDE_NO_OTHERS) {
&& frame.getExclusion() == WindowFrameExclusion.EXCLUDE_NO_OTHERS) {
WindowFrameBound following = frame.getFollowing(); WindowFrameBound following = frame.getFollowing();
if (following != null && following.getType() == WindowFrameBoundType.UNBOUNDED_FOLLOWING) { boolean unboundedFollowing = following != null
aggregateWholePartition(session, result, ordered, rowIdColumn); && following.getType() == WindowFrameBoundType.UNBOUNDED_FOLLOWING;
} else { if (frame.getStarting().getType() == WindowFrameBoundType.UNBOUNDED_PRECEDING) {
aggregateFastPartition(session, result, ordered, rowIdColumn, grouped); if (unboundedFollowing) {
aggregateWholePartition(session, result, ordered, rowIdColumn);
} else {
aggregateFastPartition(session, result, ordered, rowIdColumn, grouped);
}
return;
}
if (unboundedFollowing) {
aggregateFastPartitionInReverse(session, result, ordered, rowIdColumn, grouped);
return;
} }
return;
} }
// All other types of frames (slow) // All other types of frames (slow)
int size = ordered.size(); int size = ordered.size();
...@@ -138,6 +145,28 @@ public abstract class AbstractAggregate extends DataAnalysisOperation { ...@@ -138,6 +145,28 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
} }
} }
private void aggregateFastPartitionInReverse(Session session, HashMap<Integer, Value> result,
ArrayList<Value[]> ordered, int rowIdColumn, boolean grouped) {
Object aggregateData = createAggregateData();
int firstIncludedRow = ordered.size();
for (int i = firstIncludedRow - 1; i >= 0;) {
int newLast = over.getWindowFrame().getStartIndex(session, ordered, getOverOrderBySort(), i);
assert newLast <= firstIncludedRow;
if (newLast < firstIncludedRow) {
for (int j = firstIncludedRow - 1; j >= newLast; j--) {
updateFromExpressions(session, aggregateData, ordered.get(j));
}
firstIncludedRow = newLast;
}
Value[] lastRowInGroup = ordered.get(i), currentRowInGroup = lastRowInGroup;
Value r = getAggregatedValue(session, aggregateData);
do {
result.put(currentRowInGroup[rowIdColumn].getInt(), r);
} while (--i >= 0 && grouped
&& overOrderBySort.compare(lastRowInGroup, currentRowInGroup = ordered.get(i)) == 0);
}
}
private int processGroup(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered, private int processGroup(Session session, HashMap<Integer, Value> result, ArrayList<Value[]> ordered,
int rowIdColumn, int i, int size, Object aggregateData, boolean grouped) { int rowIdColumn, int i, int size, Object aggregateData, boolean grouped) {
Value[] firstRowInGroup = ordered.get(i), currentRowInGroup = firstRowInGroup; Value[] firstRowInGroup = ordered.get(i), currentRowInGroup = firstRowInGroup;
......
...@@ -424,6 +424,32 @@ public final class WindowFrame { ...@@ -424,6 +424,32 @@ public final class WindowFrame {
: plainIterator(orderedRows, startIndex, endIndex, reverse); : plainIterator(orderedRows, startIndex, endIndex, reverse);
} }
/**
* Returns start index of this frame,
*
* @param session
* the session
* @param orderedRows
* ordered rows
* @param sortOrder
* sort order
* @param currentRow
* index of the current row
* @return start index
* @throws UnsupportedOperationException
* if exclusion clause is not EXCLUDE NO OTHERS
*/
public int getStartIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow) {
if (exclusion != WindowFrameExclusion.EXCLUDE_NO_OTHERS) {
throw new UnsupportedOperationException();
}
int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, false);
if (startIndex < 0) {
startIndex = 0;
}
return startIndex;
}
/** /**
* Returns end index of this frame, * Returns end index of this frame,
* *
......
...@@ -371,7 +371,7 @@ SELECT *, ...@@ -371,7 +371,7 @@ SELECT *,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) U_P, ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) U_P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) P, ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) F, ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) F,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) U_F ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) U_F
FROM TEST; FROM TEST;
> ID VALUE U_P P F U_F > ID VALUE U_P P F U_F
> -- ----- ------------------ ------------ --------------- ------------------ > -- ----- ------------------ ------------ --------------- ------------------
...@@ -451,11 +451,11 @@ SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 2 PRECEDING A ...@@ -451,11 +451,11 @@ SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 2 PRECEDING A
SELECT ID, VALUE, SELECT ID, VALUE,
ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) CP, ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) CP,
ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) CF, ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) CF,
ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) RP, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) RP,
ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) RF, ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) RF,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) GP, ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) GP,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) GF ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) GF
FROM TEST; FROM TEST;
> ID VALUE CP CF RP RF GP GF > ID VALUE CP CF RP RF GP GF
> -- ----- ------------------------ ------------------------ ------------------------ ------------------------ ------------------------ ------------------------ > -- ----- ------------------------ ------------------------ ------------------------ ------------------------ ------------------------ ------------------------
...@@ -545,11 +545,11 @@ SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 1 FOLLOWING A ...@@ -545,11 +545,11 @@ SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 1 FOLLOWING A
SELECT ID, VALUE, SELECT ID, VALUE,
ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) CP, ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) CP,
ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) CF, ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) CF,
ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) RP, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) RP,
ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) RF, ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) RF,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) GP, ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) GP,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) GF ARRAY_AGG(ID ORDER BY ID) OVER (ORDER BY VALUE GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) GF
FROM TEST; FROM TEST;
> ID VALUE CP CF RP RF GP GF > ID VALUE CP CF RP RF GP GF
> -- ----- ------------------------ ------------------------ ------------------------ ------------------------ ------------------------ ------------------------ > -- ----- ------------------------ ------------------------ ------------------------ ------------------------ ------------------------ ------------------------
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论