22
22
23
23
import org .apache .doris .nereids .CascadesContext ;
24
24
import org .apache .doris .nereids .properties .OrderKey ;
25
+ import org .apache .doris .nereids .trees .expressions .Expression ;
25
26
import org .apache .doris .nereids .trees .plans .Plan ;
26
27
import org .apache .doris .nereids .trees .plans .physical .PhysicalDistribute ;
27
28
import org .apache .doris .nereids .trees .plans .physical .PhysicalHashAggregate ;
28
29
import org .apache .doris .nereids .trees .plans .physical .PhysicalHashAggregate .TopNOptInfo ;
29
30
import org .apache .doris .nereids .trees .plans .physical .PhysicalLimit ;
31
+ import org .apache .doris .nereids .trees .plans .physical .PhysicalProject ;
30
32
import org .apache .doris .nereids .trees .plans .physical .PhysicalTopN ;
31
33
34
+ import com .google .common .collect .Sets ;
35
+
36
+ import java .util .HashSet ;
32
37
import java .util .List ;
38
+ import java .util .Set ;
33
39
import java .util .stream .Collectors ;
34
40
35
41
/**
46
52
public class PushLimitToLocalAgg extends PlanPostProcessor {
47
53
@ Override
48
54
public Plan visitPhysicalTopN (PhysicalTopN <? extends Plan > topN , CascadesContext ctx ) {
49
- if (topN .child () instanceof PhysicalHashAggregate ) {
50
- PhysicalHashAggregate <? extends Plan > upperAgg = (PhysicalHashAggregate <? extends Plan >) topN .child ();
55
+ Plan topnChild = topN .child ();
56
+ if (topnChild instanceof PhysicalProject ) {
57
+ topnChild = topnChild .child (0 );
58
+ }
59
+ if (topnChild instanceof PhysicalHashAggregate ) {
60
+ PhysicalHashAggregate <? extends Plan > upperAgg = (PhysicalHashAggregate <? extends Plan >) topnChild ;
51
61
upperAgg .setTopn (new TopNOptInfo (
52
62
topN .getOrderKeys (),
53
63
topN .getLimit () + topN .getOffset ()));
54
64
if (upperAgg .getAggPhase ().isGlobal ()) {
55
65
if (upperAgg .child () instanceof PhysicalDistribute
56
66
&& upperAgg .child ().child (0 ) instanceof PhysicalHashAggregate ) {
57
- PhysicalHashAggregate <? extends Plan > bottomAgg =
58
- (PhysicalHashAggregate <? extends Plan >) upperAgg .child ().child (0 );
59
- bottomAgg .setTopn (new TopNOptInfo (
60
- topN .getOrderKeys (),
61
- topN .getLimit () + topN .getOffset ()));
62
- bottomAgg .child ().accept (this , ctx );
67
+ if (checkTopnKeyAndGroupKey (topN , upperAgg )) {
68
+ PhysicalHashAggregate <? extends Plan > bottomAgg =
69
+ (PhysicalHashAggregate <? extends Plan >) upperAgg .child ().child (0 );
70
+ bottomAgg .setTopn (new TopNOptInfo (
71
+ topN .getOrderKeys (),
72
+ topN .getLimit () + topN .getOffset ()));
73
+ }
63
74
}
64
75
}
65
- } else {
66
- topN .child ().accept (this , ctx );
67
76
}
77
+ topN .child ().accept (this , ctx );
68
78
return topN ;
69
79
}
70
80
81
+ /**
82
+ *
83
+ * @param topN
84
+ * @param agg
85
+ * @return true, if topn order key set equals to agg group keys, ignore asc/desc and null_first
86
+ */
87
+ private boolean checkTopnKeyAndGroupKey (PhysicalTopN <? extends Plan > topN ,
88
+ PhysicalHashAggregate <? extends Plan > agg ) {
89
+ Set <Expression > orderKeys = topN .getOrderKeys ().stream ()
90
+ .map (OrderKey ::getExpr ).collect (Collectors .toSet ());
91
+ Set <Expression > groupKeys = new HashSet <>(agg .getGroupByExpressions ());
92
+ return groupKeys .size () == orderKeys .size () && groupKeys .containsAll (orderKeys );
93
+ }
94
+
71
95
@ Override
72
96
public Plan visitPhysicalLimit (PhysicalLimit <? extends Plan > limit , CascadesContext ctx ) {
73
- if (limit .child () instanceof PhysicalHashAggregate ) {
74
- PhysicalHashAggregate <? extends Plan > upperAgg = (PhysicalHashAggregate <? extends Plan >) limit .child ();
97
+ Plan limitChild = limit .child ();
98
+ if (limitChild instanceof PhysicalProject ) {
99
+ limitChild = limitChild .child (0 );
100
+ }
101
+ if (limitChild instanceof PhysicalHashAggregate ) {
102
+ PhysicalHashAggregate <? extends Plan > upperAgg = (PhysicalHashAggregate <? extends Plan >) limitChild ;
75
103
upperAgg .setTopn (new TopNOptInfo (
76
104
generateOrderKeysByGroupKeys (upperAgg ),
77
105
limit .getLimit () + limit .getOffset ()));
@@ -83,12 +111,11 @@ public Plan visitPhysicalLimit(PhysicalLimit<? extends Plan> limit, CascadesCont
83
111
bottomAgg .setTopn (new TopNOptInfo (
84
112
generateOrderKeysByGroupKeys (bottomAgg ),
85
113
limit .getLimit () + limit .getOffset ()));
86
- bottomAgg .child ().accept (this , ctx );
87
114
}
88
115
}
89
- } else {
90
- limit .child ().accept (this , ctx );
91
116
}
117
+ limit .child ().accept (this , ctx );
118
+
92
119
return limit ;
93
120
}
94
121
0 commit comments