@Override protected void doPush(OptimizationContext.OperatorContext opCtx, Configuration configuration) { // Trigger the push for each of the alternativeTraversals. this.pushThroughAlternatives(opCtx, configuration); // Somehow merge the CardinalityEstimates from the alternativeTraversals to the final ones for the opCtx. this.pickCardinalities(opCtx); }
/** * Pick {@link CardinalityEstimate}s for each of the {@link OutputSlot}s within the {@code opCtx}. */ protected void pickCardinalities(OptimizationContext.OperatorContext opCtx) { final OperatorAlternative operatorAlternative = (OperatorAlternative) opCtx.getOperator(); // For each relevant OutputSlot of the OperatorAlternative... for (int outputIndex : this.relevantOutputIndices) { final OutputSlot<?> output = operatorAlternative.getOutput(outputIndex); CardinalityEstimate bestEstimate = opCtx.getOutputCardinality(output.getIndex()); // ...and dor each corresponding OutputSlot in each Alternative... for (OperatorAlternative.Alternative alternative : operatorAlternative.getAlternatives()) { // ...pick the best CardinalityEstimate. final OutputSlot<?> innerOutput = alternative.getSlotMapping().resolveUpstream(output); if (innerOutput == null) continue; final OptimizationContext.OperatorContext innerOpCtx = opCtx.getOptimizationContext() .getOperatorContext(innerOutput.getOwner()); final CardinalityEstimate newEstimate = innerOpCtx.getOutputCardinality(innerOutput.getIndex()); if (newEstimate == null) { logger.warn("No cardinality estimate for {}.", innerOutput); continue; } bestEstimate = this.choose(bestEstimate, newEstimate); } // Finalize the decision. opCtx.setOutputCardinality(output.getIndex(), bestEstimate); } }