diff --git a/fe/src/com/baidu/palo/analysis/Analyzer.java b/fe/src/com/baidu/palo/analysis/Analyzer.java index 5b071819b87f99..457962ba8476ed 100644 --- a/fe/src/com/baidu/palo/analysis/Analyzer.java +++ b/fe/src/com/baidu/palo/analysis/Analyzer.java @@ -59,6 +59,7 @@ import java.util.Calendar; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -1543,4 +1544,53 @@ public boolean isOuterJoined(TupleId tid) { public boolean containSubquery() { return globalState.containsSubquery; } + + /** + * Mark slots that are being referenced by the plan tree itself or by the outputExprs exprs as materialized. If the + * latter is null, mark all slots in planRoot's tupleIds() as being referenced. All aggregate slots are + * materialized. + *

+ * TODO: instead of materializing everything produced by the plan root, derived referenced slots from destination + * fragment and add a materialization node if not all output is needed by destination fragment TODO 2: should the + * materialization decision be cost-based? + */ + public void markRefdSlots(Analyzer analyzer, PlanNode planRoot, + List outputExprs, AnalyticInfo analyticInfo) { + if (planRoot == null) { + return; + } + List refdIdList = Lists.newArrayList(); + planRoot.getMaterializedIds(analyzer, refdIdList); + if (outputExprs != null) { + Expr.getIds(outputExprs, null, refdIdList); + } + + HashSet refdIds = Sets.newHashSet(refdIdList); + for (TupleDescriptor tupleDesc : analyzer.getDescTbl().getTupleDescs()) { + for (SlotDescriptor slotDesc : tupleDesc.getSlots()) { + if (refdIds.contains(slotDesc.getId())) { + slotDesc.setIsMaterialized(true); + } + } + } + if (analyticInfo != null) { + ArrayList list = analyticInfo.getOutputTupleDesc().getSlots(); + + for (SlotDescriptor slotDesc : list) { + if (refdIds.contains(slotDesc.getId())) { + slotDesc.setIsMaterialized(true); + } + } + } + if (outputExprs == null) { + // mark all slots in planRoot.getTupleIds() as materialized + ArrayList tids = planRoot.getTupleIds(); + for (TupleId tid : tids) { + TupleDescriptor tupleDesc = analyzer.getDescTbl().getTupleDesc(tid); + for (SlotDescriptor slotDesc : tupleDesc.getSlots()) { + slotDesc.setIsMaterialized(true); + } + } + } + } } diff --git a/fe/src/com/baidu/palo/planner/Planner.java b/fe/src/com/baidu/palo/planner/Planner.java index 94980159103ae8..85cc5c529ad2fa 100644 --- a/fe/src/com/baidu/palo/planner/Planner.java +++ b/fe/src/com/baidu/palo/planner/Planner.java @@ -107,55 +107,6 @@ private void setResultExprScale(Analyzer analyzer, ArrayList outputExprs) } } - /** - * Mark slots that are being referenced by the plan tree itself or by the outputExprs exprs as materialized. If the - * latter is null, mark all slots in planRoot's tupleIds() as being referenced. All aggregate slots are - * materialized. - *

- * TODO: instead of materializing everything produced by the plan root, derived referenced slots from destination - * fragment and add a materialization node if not all output is needed by destination fragment TODO 2: should the - * materialization decision be cost-based? - */ - private void markRefdSlots(Analyzer analyzer, PlanNode planRoot, - List outputExprs, AnalyticInfo analyticInfo) { - if (planRoot == null) { - return; - } - List refdIdList = Lists.newArrayList(); - planRoot.getMaterializedIds(analyzer, refdIdList); - if (outputExprs != null) { - Expr.getIds(outputExprs, null, refdIdList); - } - - HashSet refdIds = Sets.newHashSet(refdIdList); - for (TupleDescriptor tupleDesc : analyzer.getDescTbl().getTupleDescs()) { - for (SlotDescriptor slotDesc : tupleDesc.getSlots()) { - if (refdIds.contains(slotDesc.getId())) { - slotDesc.setIsMaterialized(true); - } - } - } - if (analyticInfo != null) { - ArrayList list = analyticInfo.getOutputTupleDesc().getSlots(); - - for (SlotDescriptor slotDesc : list) { - if (refdIds.contains(slotDesc.getId())) { - slotDesc.setIsMaterialized(true); - } - } - } - if (outputExprs == null) { - // mark all slots in planRoot.getTupleIds() as materialized - ArrayList tids = planRoot.getTupleIds(); - for (TupleId tid : tids) { - TupleDescriptor tupleDesc = analyzer.getDescTbl().getTupleDesc(tid); - for (SlotDescriptor slotDesc : tupleDesc.getSlots()) { - slotDesc.setIsMaterialized(true); - } - } - } - } - /** * Return combined explain string for all plan fragments. */ @@ -201,7 +152,7 @@ public void createPlanFragments(StatementBase statment, Analyzer analyzer, TQuer } // compute referenced slots before calling computeMemLayout() - markRefdSlots(analyzer, singleNodePlan, resultExprs, null); + analyzer.markRefdSlots(analyzer, singleNodePlan, resultExprs, null); setResultExprScale(analyzer, queryStmt.getResultExprs()); diff --git a/fe/src/com/baidu/palo/planner/SingleNodePlanner.java b/fe/src/com/baidu/palo/planner/SingleNodePlanner.java index 8736e176eeb6de..a3ac1e914f865c 100644 --- a/fe/src/com/baidu/palo/planner/SingleNodePlanner.java +++ b/fe/src/com/baidu/palo/planner/SingleNodePlanner.java @@ -651,26 +651,23 @@ private PlanNode createSelectPlan(SelectStmt selectStmt, Analyzer analyzer, long // add aggregate node here AggregateInfo aggInfo = selectStmt.getAggInfo(); - /* + // for case: select count(*) from (select col from table) t // for simple, we just materialize sub tree if has count star if (aggInfo != null) { for (FunctionCallExpr aggExpr : aggInfo.getAggregateExprs()) { if (aggExpr.isCountStar()) { - LOG.debug("count(*) to {}", root.debugString()); - markRefdSlots(analyzer, root, null, null); + analyzer.markRefdSlots(analyzer, root, null, null); break; } } for (Expr groupExpr : aggInfo.getGroupingExprs()) { if (groupExpr.isConstant()) { - LOG.debug("count(distinct 1) to {}", root.debugString()); - markRefdSlots(analyzer, root, null, null); + analyzer.markRefdSlots(analyzer, root, null, null); break; } } } - */ turnOffPreAgg(aggInfo, selectStmt, analyzer, root);