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); }
// 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); }