diff --git ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java index 1feb1fd..f45d9c0 100644 --- ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java +++ ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java @@ -1293,13 +1293,46 @@ private void inferPKFKRelationship() { List result = Lists.newArrayList(); for (Integer idx : opsWithPK) { Operator op = ops.get(idx); - TableScanOperator tsOp = OperatorUtils - .findSingleOperatorUpstream(op, TableScanOperator.class); + float selectivity = getSelectivitySimpleTree(op); + result.add(selectivity); + } + return result; + } + + private float getSelectivitySimpleTree(Operator op) { + TableScanOperator tsOp = OperatorUtils + .findSingleOperatorUpstream(op, TableScanOperator.class); + if (tsOp == null) { + // complex tree with multiple parents + return getSelectivityComplexTree(op); + } else { + // simple tree with single parent long inputRow = tsOp.getStatistics().getNumRows(); long outputRow = op.getStatistics().getNumRows(); - result.add((float) outputRow / (float) inputRow); + return (float) outputRow / (float) inputRow; } - return result; + } + + private float getSelectivityComplexTree(Operator op) { + Operator multiParentOp = null; + Operator currentOp = op; + while(multiParentOp == null) { + if (op.getParentOperators().size() > 1) { + multiParentOp = op; + } else { + op = op.getParentOperators().get(0); + } + } + + float selMultiParent = 1.0f; + for(Operator parent : multiParentOp.getParentOperators()) { + selMultiParent *= getSelectivitySimpleTree(parent); + } + + float selCurrOp = (float) currentOp.getStatistics().getNumRows() / + (float) multiParentOp.getStatistics().getNumRows(); + + return selCurrOp * selMultiParent; } /**