public Double getPercentageOriginalRows(UnionRelBase rel) { double numerator = 0.0; double denominator = 0.0; // Ignore rel.isDistinct() because it's the same as an aggregate. // REVIEW jvs 28-Mar-2006: The original Broadbase formula was broken. // It was multiplying percentage into the numerator term rather than // than dividing it out of the denominator term, which would be OK if // there weren't summation going on. Probably the cause of the error // was the desire to avoid division by zero, which I don't know how to // handle so I punt, meaning we return a totally wrong answer in the // case where a huge table has been completely filtered away. for (RelNode input : rel.getInputs()) { double rowCount = RelMetadataQuery.getRowCount(input); double percentage = RelMetadataQuery.getPercentageOriginalRows(input); if (percentage != 0.0) { denominator += rowCount / percentage; numerator += rowCount; } } return quotientForPercentage(numerator, denominator); }
// Ditto for getNonCumulativeCost public RelOptCost getCumulativeCost(RelNode rel) { RelOptCost cost = RelMetadataQuery.getNonCumulativeCost(rel); List<RelNode> inputs = rel.getInputs(); for (RelNode input : inputs) { cost = cost.plus(RelMetadataQuery.getCumulativeCost(input)); } return cost; }
public Double getPercentageOriginalRows(JoinRelBase rel) { // Assume any single-table filter conditions have already // been pushed down. // REVIEW jvs 28-Mar-2006: As with aggregation, this is // oversimplified. // REVIEW jvs 28-Mar-2006: need any special casing for SemiJoinRel? double left = RelMetadataQuery.getPercentageOriginalRows(rel.getLeft()); double right = RelMetadataQuery.getPercentageOriginalRows(rel.getRight()); return left * right; }
public Double getPercentageOriginalRows(AggregateRelBase rel) { // REVIEW jvs 28-Mar-2006: The assumption here seems to be that // aggregation does not apply any filtering, so it does not modify the // percentage. That's very much oversimplified. return RelMetadataQuery.getPercentageOriginalRows(rel.getChild()); }
// implement RelNode public RelOptCost computeSelfCost(RelOptPlanner planner) { double dRows = RelMetadataQuery.getRowCount(this); // Assume CPU is negligible since values are precomputed. double dCpu = 1; double dIo = 0; return planner.makeCost(dRows, dCpu, dIo); }
// Catch-all rule when none of the others apply. public Double getPercentageOriginalRows(RelNode rel) { if (rel.getInputs().size() > 1) { // No generic formula available for multiple inputs. return null; } if (rel.getInputs().size() == 0) { // Assume no filtering happening at leaf. return 1.0; } RelNode child = rel.getInputs().get(0); Double childPercentage = RelMetadataQuery.getPercentageOriginalRows(child); if (childPercentage == null) { return null; } // Compute product of percentage filtering from this rel (assuming any // filtering is the effect of single-table filters) with the percentage // filtering performed by the child. Double relPercentage = quotientForPercentage( RelMetadataQuery.getRowCount(rel), RelMetadataQuery.getRowCount(child)); if (relPercentage == null) { return null; } double percent = relPercentage * childPercentage; // this check is needed in cases where this method is called on a // physical rel if ((percent < 0.0) || (percent > 1.0)) { return null; } return relPercentage * childPercentage; }
public RelOptCost computeSelfCost(RelOptPlanner planner) { double dRows = RelMetadataQuery.getRowCount(this); double dCpu = RelMetadataQuery.getRowCount(getChild()) * program.getExprCount(); double dIo = 0; return planner.makeCost(dRows, dCpu, dIo); }