diff --git ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/RelOptHiveTable.java ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/RelOptHiveTable.java index 562142d..8bddb30 100644 --- ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/RelOptHiveTable.java +++ ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/RelOptHiveTable.java @@ -293,4 +293,23 @@ private void updateColStats(Set projIndxLst) { return colStatsBldr.build(); } + + /* + * use to check if a set of columns are all partition columns. + * true only if: + * - there is a prunedPartList in place + * - all columns in BitSet are partition + * columns. + */ + public boolean containsPartitionColumnsOnly(BitSet cols) { + if (partitionList == null) { + return false; + } + for (int i = cols.nextSetBit(0); i >= 0; i++, i = cols.nextSetBit(i + 1)) { + if (!m_hivePartitionColsMap.containsKey(i)) { + return false; + } + } + return true; + } } diff --git ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/stats/FilterSelectivityEstimator.java ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/stats/FilterSelectivityEstimator.java index 825ecfc..f8e3238 100644 --- ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/stats/FilterSelectivityEstimator.java +++ ql/src/java/org/apache/hadoop/hive/ql/optimizer/optiq/stats/FilterSelectivityEstimator.java @@ -1,11 +1,20 @@ package org.apache.hadoop.hive.ql.optimizer.optiq.stats; +import java.util.BitSet; + +import org.apache.hadoop.hive.ql.optimizer.optiq.RelOptHiveTable; +import org.apache.hadoop.hive.ql.optimizer.optiq.reloperators.HiveTableScanRel; +import org.eigenbase.rel.FilterRelBase; +import org.eigenbase.rel.ProjectRel; +import org.eigenbase.rel.ProjectRelBase; import org.eigenbase.rel.RelNode; import org.eigenbase.rel.metadata.RelMetadataQuery; +import org.eigenbase.relopt.RelOptUtil; import org.eigenbase.relopt.RelOptUtil.InputReferencedVisitor; import org.eigenbase.rex.RexCall; import org.eigenbase.rex.RexInputRef; import org.eigenbase.rex.RexNode; +import org.eigenbase.rex.RexUtil; import org.eigenbase.rex.RexVisitorImpl; import org.eigenbase.sql.SqlKind; @@ -28,6 +37,15 @@ public Double visitCall(RexCall call) { return 1.0; } + /* + * Ignore any predicates on partition columns + * because we have already accounted for these in + * the Table row count. + */ + if (isPartitionPredicate(call, m_childRel)) { + return 1.0; + } + Double selectivity = null; SqlKind op = call.getKind(); @@ -178,4 +196,19 @@ private Double getMaxNDV(RexCall call) { return maxNDV; } + + private boolean isPartitionPredicate(RexNode expr, RelNode r) { + if ( r instanceof ProjectRelBase ) { + expr = RelOptUtil.pushFilterPastProject(expr, (ProjectRelBase) r); + return isPartitionPredicate(expr, ((ProjectRelBase) r).getChild()); + } else if ( r instanceof FilterRelBase ) { + isPartitionPredicate(expr, ((ProjectRelBase) r).getChild()); + } else if ( r instanceof HiveTableScanRel ) { + RelOptHiveTable table = (RelOptHiveTable) + ((HiveTableScanRel)r).getTable(); + BitSet cols = RelOptUtil.InputFinder.bits(expr); + return table.containsPartitionColumnsOnly(cols); + } + return false; + } }