diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/stats/HiveRelMdRowCount.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/stats/HiveRelMdRowCount.java index 7bba80b..f8201b7 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/stats/HiveRelMdRowCount.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/stats/HiveRelMdRowCount.java @@ -19,7 +19,9 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.hep.HepRelVertex; @@ -58,51 +60,76 @@ public static final RelMetadataProvider SOURCE = ReflectiveRelMetadataProvider .reflectiveSource(BuiltInMethod.ROW_COUNT.method, new HiveRelMdRowCount()); + protected Map memoMap = new WeakHashMap<>(); + protected HiveRelMdRowCount() { super(); } public Double getRowCount(Join join, RelMetadataQuery mq) { - PKFKRelationInfo pkfk = analyzeJoinForPKFK(join, mq); - if (pkfk != null) { - double selectivity = (pkfk.pkInfo.selectivity * pkfk.ndvScalingFactor); - selectivity = Math.min(1.0, selectivity); - if (LOG.isDebugEnabled()) { - LOG.debug("Identified Primary - Foreign Key relation: {} {}",RelOptUtil.toString(join), pkfk); + Double ret = memoMap.get(join); + if (ret == null) { + PKFKRelationInfo pkfk = analyzeJoinForPKFK(join, mq); + if (pkfk != null) { + double selectivity = (pkfk.pkInfo.selectivity * pkfk.ndvScalingFactor); + selectivity = Math.min(1.0, selectivity); + if (LOG.isDebugEnabled()) { + LOG.debug("Identified Primary - Foreign Key relation: {} {}",RelOptUtil.toString(join), pkfk); + } + return pkfk.fkInfo.rowCount * selectivity; + } + ret = join.getRows(); + if (ret != null) { + memoMap.put(join, ret); } - return pkfk.fkInfo.rowCount * selectivity; } - return join.getRows(); + return ret; } @Override public Double getRowCount(SemiJoin rel, RelMetadataQuery mq) { - PKFKRelationInfo pkfk = analyzeJoinForPKFK(rel, mq); - if (pkfk != null) { - double selectivity = (pkfk.pkInfo.selectivity * pkfk.ndvScalingFactor); - selectivity = Math.min(1.0, selectivity); - if (LOG.isDebugEnabled()) { - LOG.debug("Identified Primary - Foreign Key relation: {} {}", RelOptUtil.toString(rel), pkfk); + Double ret = memoMap.get(rel); + if (ret == null) { + PKFKRelationInfo pkfk = analyzeJoinForPKFK(rel, mq); + if (pkfk != null) { + double selectivity = (pkfk.pkInfo.selectivity * pkfk.ndvScalingFactor); + selectivity = Math.min(1.0, selectivity); + if (LOG.isDebugEnabled()) { + LOG.debug("Identified Primary - Foreign Key relation: {} {}", RelOptUtil.toString(rel), pkfk); + } + ret = pkfk.fkInfo.rowCount * selectivity; + } else { + ret = super.getRowCount(rel, mq); + } + if (ret != null) { + memoMap.put(rel, ret); } - return pkfk.fkInfo.rowCount * selectivity; } - return super.getRowCount(rel, mq); + return ret; } @Override public Double getRowCount(Sort rel, RelMetadataQuery mq) { - final Double rowCount = mq.getRowCount(rel.getInput()); - if (rowCount != null && rel.fetch != null) { - final int offset = rel.offset == null ? 0 : RexLiteral.intValue(rel.offset); - final int limit = RexLiteral.intValue(rel.fetch); - final Double offsetLimit = new Double(offset + limit); - // offsetLimit is smaller than rowCount of the input operator - // thus, we return the offsetLimit - if (offsetLimit < rowCount) { - return offsetLimit; + Double ret = memoMap.get(rel); + if (ret == null) { + final Double rowCount = mq.getRowCount(rel.getInput()); + if (rowCount != null && rel.fetch != null) { + final int offset = rel.offset == null ? 0 : RexLiteral.intValue(rel.offset); + final int limit = RexLiteral.intValue(rel.fetch); + final Double offsetLimit = new Double(offset + limit); + // offsetLimit is smaller than rowCount of the input operator + // thus, we return the offsetLimit + if (offsetLimit < rowCount) { + ret = offsetLimit; + } + } else { + ret = rowCount; + } + if (ret != null) { + return ret; } } - return rowCount; + return ret; } static class PKFKRelationInfo {