@Override public PhysicalOperator getPhysicalOperator(PhysicalPlanCreator creator) throws IOException { Prel child = (Prel) this.getInput(); PhysicalOperator childPOP = child.getPhysicalOperator(creator); UnionExchange g = new UnionExchange(childPOP); return creator.addMetadata(this, g); }
@Override public void onMatch(RelOptRuleCall call) { final LimitPrel limit = (LimitPrel) call.rel(0); final UnionExchangePrel unionExchangePrel = (UnionExchangePrel) call.rel(1); RelNode child = unionExchangePrel.getInput(); final int offset = limit.getOffset() != null ? Math.max(0, RexLiteral.intValue(limit.getOffset())) : 0; final int fetch = Math.max(0, RexLiteral.intValue(limit.getFetch())); // child Limit uses conservative approach: use offset 0 and fetch = parent limit offset + parent limit fetch. final RexNode childFetch = limit.getCluster().getRexBuilder().makeExactLiteral(BigDecimal.valueOf(offset + fetch)); final RelNode limitUnderExchange = new LimitPrel(child.getCluster(), child.getTraitSet(), child, null, childFetch); final RelNode newUnionExch = new UnionExchangePrel(unionExchangePrel.getCluster(), unionExchangePrel.getTraitSet(), limitUnderExchange); final RelNode limitAboveExchange = new LimitPrel(limit.getCluster(), limit.getTraitSet(), newUnionExch, limit.getOffset(), limit.getFetch(), true); call.transformTo(limitAboveExchange); }
/** * A UnionExchange processes a total of M rows coming from N senders and * combines them into a single output stream. Note that there is * no sort or merge operation going on. For costing purposes, we can * assume each sender is sending M/N rows to a single receiver. * (See DremioCost for symbol notations) * C = CPU cost of SV remover for M/N rows * + Network cost of sending M/N rows to 1 destination. * So, C = (s * M/N) + (w * M/N) * Total cost = N * C */ @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) { if (PrelUtil.getSettings(getCluster()).useDefaultCosting()) { return super.computeSelfCost(planner).multiplyBy(.1); } RelNode child = this.getInput(); double inputRows = mq.getRowCount(child); int rowWidth = child.getRowType().getFieldCount() * DremioCost.AVG_FIELD_WIDTH; double svrCpuCost = DremioCost.SVR_CPU_COST * inputRows; double networkCost = DremioCost.BYTE_NETWORK_COST * inputRows * rowWidth; Factory costFactory = (Factory)planner.getCostFactory(); return costFactory.makeCost(inputRows, svrCpuCost, 0, networkCost); }