Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
UnionNode.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.planner;
16 
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Comparator;
20 import java.util.List;
21 
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 
30 import com.cloudera.impala.common.Pair;
31 import com.cloudera.impala.thrift.TExplainLevel;
32 import com.cloudera.impala.thrift.TExpr;
33 import com.cloudera.impala.thrift.TPlanNode;
34 import com.cloudera.impala.thrift.TPlanNodeType;
35 import com.cloudera.impala.thrift.TUnionNode;
36 import com.google.common.base.Preconditions;
37 import com.google.common.collect.Lists;
38 
43 public class UnionNode extends PlanNode {
44  private final static Logger LOG = LoggerFactory.getLogger(UnionNode.class);
45 
46  // Expr lists corresponding to the input query stmts.
47  // The ith resultExprList belongs to the ith child.
48  // All exprs are resolved to base tables.
49  protected List<List<Expr>> resultExprLists_ = Lists.newArrayList();
50 
51  // Expr lists that originate from constant select stmts.
52  // We keep them separate from the regular expr lists to avoid null children.
53  protected List<List<Expr>> constExprLists_ = Lists.newArrayList();
54 
55  // Materialized result/const exprs corresponding to materialized slots.
56  // Set in init() and substituted against the corresponding child's output smap.
57  protected List<List<Expr>> materializedResultExprLists_ = Lists.newArrayList();
58  protected List<List<Expr>> materializedConstExprLists_ = Lists.newArrayList();
59 
60  protected final TupleId tupleId_;
61 
62  protected UnionNode(PlanNodeId id, TupleId tupleId) {
63  super(id, Lists.newArrayList(tupleId), "UNION");
64  tupleId_ = tupleId;
65  }
66 
67  public void addConstExprList(List<Expr> exprs) { constExprLists_.add(exprs); }
68 
72  public void addChild(PlanNode node, List<Expr> baseTblResultExprs) {
73  super.addChild(node);
74  resultExprLists_.add(baseTblResultExprs);
75  if (baseTblResultExprs != null) {
76  // if we're materializing output, we can only do that into a single
77  // output tuple
78  Preconditions.checkState(tupleIds_.size() == 1, tupleIds_.size());
79  }
80  }
81 
82  @Override
83  public void computeStats(Analyzer analyzer) {
84  super.computeStats(analyzer);
85  cardinality_ = constExprLists_.size();
86  for (PlanNode child: children_) {
87  // ignore missing child cardinality info in the hope it won't matter enough
88  // to change the planning outcome
89  if (child.cardinality_ > 0) {
90  cardinality_ = addCardinalities(cardinality_, child.cardinality_);
91  }
92  }
93  // The number of nodes of a union node is -1 (invalid) if all the referenced tables
94  // are inline views (e.g. select 1 FROM (VALUES(1 x, 1 y)) a FULL OUTER JOIN
95  // (VALUES(1 x, 1 y)) b ON (a.x = b.y)). We need to set the correct value.
96  if (numNodes_ == -1) numNodes_ = 1;
97 
98  LOG.debug("stats Union: cardinality=" + Long.toString(cardinality_));
99  }
100 
115  public void reorderOperands(Analyzer analyzer) {
116  Preconditions.checkNotNull(fragment_,
117  "Operands can only be reordered on the fragmented plan.");
118 
119  // List of estimated per-host memory consumption (first) by child index (second).
120  List<Pair<Long, Integer>> memByChildIdx = Lists.newArrayList();
121  for (int i = 0; i < children_.size(); ++i) {
122  PlanNode child = children_.get(i);
123  child.computeCosts(analyzer.getQueryCtx().request.getQuery_options());
124  memByChildIdx.add(new Pair<Long, Integer>(child.getPerHostMemCost(), i));
125  }
126 
127  Collections.sort(memByChildIdx,
128  new Comparator<Pair<Long, Integer>>() {
129  public int compare(Pair<Long, Integer> a, Pair<Long, Integer> b) {
130  PlanNode aNode = children_.get(a.second);
131  PlanNode bNode = children_.get(b.second);
132  // Order scan nodes last because they can dynamically scale down their mem.
133  if (bNode instanceof ScanNode && !(aNode instanceof ScanNode)) return -1;
134  if (aNode instanceof ScanNode && !(bNode instanceof ScanNode)) return 1;
135  long diff = b.first - a.first;
136  return (diff < 0 ? -1 : (diff > 0 ? 1 : 0));
137  }
138  });
139 
140  List<List<Expr>> newResultExprLists = Lists.newArrayList();
141  ArrayList<PlanNode> newChildren = Lists.newArrayList();
142  for (Pair<Long, Integer> p: memByChildIdx) {
143  newResultExprLists.add(resultExprLists_.get(p.second));
144  newChildren.add(children_.get(p.second));
145  }
146  resultExprLists_ = newResultExprLists;
147  children_ = newChildren;
148  }
149 
159  @Override
160  public void init(Analyzer analyzer) throws InternalException {
161  computeMemLayout(analyzer);
162  computeStats(analyzer);
163 
164  // drop resultExprs/constExprs that aren't getting materialized (= where the
165  // corresponding output slot isn't being materialized)
166  materializedResultExprLists_.clear();
167  Preconditions.checkState(resultExprLists_.size() == children_.size());
168  List<SlotDescriptor> slots = analyzer.getDescTbl().getTupleDesc(tupleId_).getSlots();
169  for (int i = 0; i < resultExprLists_.size(); ++i) {
170  List<Expr> exprList = resultExprLists_.get(i);
171  List<Expr> newExprList = Lists.newArrayList();
172  for (int j = 0; j < exprList.size(); ++j) {
173  if (slots.get(j).isMaterialized()) newExprList.add(exprList.get(j));
174  }
175  materializedResultExprLists_.add(
176  Expr.substituteList(newExprList, getChild(i).getOutputSmap(), analyzer, true));
177  }
178  Preconditions.checkState(
179  materializedResultExprLists_.size() == getChildren().size());
180 
181  materializedConstExprLists_.clear();
182  for (List<Expr> exprList: constExprLists_) {
183  List<Expr> newExprList = Lists.newArrayList();
184  for (int i = 0; i < exprList.size(); ++i) {
185  if (slots.get(i).isMaterialized()) newExprList.add(exprList.get(i));
186  }
187  materializedConstExprLists_.add(newExprList);
188  }
189  }
190 
191  @Override
192  protected void toThrift(TPlanNode msg) {
193  Preconditions.checkState(materializedResultExprLists_.size() == children_.size());
194  List<List<TExpr>> texprLists = Lists.newArrayList();
195  for (List<Expr> exprList: materializedResultExprLists_) {
196  texprLists.add(Expr.treesToThrift(exprList));
197  }
198  List<List<TExpr>> constTexprLists = Lists.newArrayList();
199  for (List<Expr> constTexprList: materializedConstExprLists_) {
200  constTexprLists.add(Expr.treesToThrift(constTexprList));
201  }
202  msg.union_node = new TUnionNode(tupleId_.asInt(), texprLists, constTexprLists);
203  msg.node_type = TPlanNodeType.UNION_NODE;
204  }
205 
206  @Override
207  protected String getNodeExplainString(String prefix, String detailPrefix,
208  TExplainLevel detailLevel) {
209  StringBuilder output = new StringBuilder();
210  output.append(String.format("%s%s:%s\n", prefix, id_.toString(), displayName_));
211  // A UnionNode may have predicates if a union is used inside an inline view,
212  // and the enclosing select stmt has predicates referring to the inline view.
213  if (!conjuncts_.isEmpty()) {
214  output.append(detailPrefix + "predicates: " + getExplainString(conjuncts_) + "\n");
215  }
216  if (!constExprLists_.isEmpty()) {
217  output.append(detailPrefix + "constant-operands=" + constExprLists_.size() + "\n");
218  }
219  return output.toString();
220  }
221 }
void computeStats(Analyzer analyzer)
Definition: UnionNode.java:83
String getNodeExplainString(String prefix, String detailPrefix, TExplainLevel detailLevel)
Definition: UnionNode.java:207
List< List< Expr > > materializedResultExprLists_
Definition: UnionNode.java:57
ArrayList< TupleId > tupleIds_
Definition: PlanNode.java:74
void addChild(PlanNode node, List< Expr > baseTblResultExprs)
Definition: UnionNode.java:72
List< List< Expr > > constExprLists_
Definition: UnionNode.java:53
int TupleId
Definition: global-types.h:23
List< List< Expr > > resultExprLists_
Definition: UnionNode.java:49
void reorderOperands(Analyzer analyzer)
Definition: UnionNode.java:115
void addConstExprList(List< Expr > exprs)
Definition: UnionNode.java:67
void computeMemLayout(Analyzer analyzer)
Definition: PlanNode.java:475
void init(Analyzer analyzer)
Definition: UnionNode.java:160
List< List< Expr > > materializedConstExprLists_
Definition: UnionNode.java:58
UnionNode(PlanNodeId id, TupleId tupleId)
Definition: UnionNode.java:62
static long addCardinalities(long a, long b)
Definition: PlanNode.java:528