@Override protected SymbolStatsEstimate visitNode(Node node, Void context) { return SymbolStatsEstimate.unknown(); }
private static SymbolStatsEstimate estimateAggregationStats(Aggregation aggregation, PlanNodeStatsEstimate sourceStats) { requireNonNull(aggregation, "aggregation is null"); requireNonNull(sourceStats, "sourceStats is null"); // TODO implement simple aggregations like: min, max, count, sum return SymbolStatsEstimate.unknown(); } }
public SymbolStatsEstimate getSymbolStatistics(Symbol symbol) { return symbolStatistics.getOrDefault(symbol, SymbolStatsEstimate.unknown()); }
@Override protected Optional<PlanNodeStatsEstimate> doCalculate(TableScanNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types) { // TODO Construct predicate like AddExchanges's LayoutConstraintEvaluator Constraint<ColumnHandle> constraint = new Constraint<>(node.getCurrentConstraint()); TableStatistics tableStatistics = metadata.getTableStatistics(session, node.getTable(), constraint); Map<Symbol, SymbolStatsEstimate> outputSymbolStats = new HashMap<>(); for (Map.Entry<Symbol, ColumnHandle> entry : node.getAssignments().entrySet()) { Symbol symbol = entry.getKey(); Optional<ColumnStatistics> columnStatistics = Optional.ofNullable(tableStatistics.getColumnStatistics().get(entry.getValue())); outputSymbolStats.put(symbol, columnStatistics.map(statistics -> toSymbolStatistics(tableStatistics, statistics)).orElse(SymbolStatsEstimate.unknown())); } return Optional.of(PlanNodeStatsEstimate.builder() .setOutputRowCount(tableStatistics.getRowCount().getValue()) .addSymbolStatistics(outputSymbolStats) .build()); }
@Test public void testLeftJoinMissingStats() { PlanNodeStatsEstimate leftStats = planNodeStats( 1, new SymbolStatistics(LEFT_JOIN_COLUMN, SymbolStatsEstimate.unknown()), new SymbolStatistics(LEFT_OTHER_COLUMN, SymbolStatsEstimate.unknown())); PlanNodeStatsEstimate rightStats = planNodeStats( 1, new SymbolStatistics(RIGHT_JOIN_COLUMN, SymbolStatsEstimate.unknown()), new SymbolStatistics(RIGHT_OTHER_COLUMN, SymbolStatsEstimate.unknown())); assertJoinStats(LEFT, leftStats, rightStats, PlanNodeStatsEstimate.unknown()); }
return SymbolStatsEstimate.unknown();
@Override protected SymbolStatsEstimate visitFunctionCall(FunctionCall node, Void context) { Map<NodeRef<Expression>, Type> expressionTypes = getExpressionTypes(session, node, types); ExpressionInterpreter interpreter = ExpressionInterpreter.expressionOptimizer(node, metadata, session, expressionTypes); Object value = interpreter.optimize(NoOpSymbolResolver.INSTANCE); if (value == null || value instanceof NullLiteral) { return nullStatsEstimate(); } if (value instanceof Expression && !(value instanceof Literal)) { // value is not a constant return SymbolStatsEstimate.unknown(); } // value is a constant return SymbolStatsEstimate.builder() .setNullsFraction(0) .setDistinctValuesCount(1) .build(); }
@Test public void testDropNonOutputSymbols() { Symbol a = new Symbol("a"); Symbol b = new Symbol("b"); Symbol c = new Symbol("c"); PlanNodeStatsEstimate estimate = PlanNodeStatsEstimate.builder() .setOutputRowCount(40) .addSymbolStatistics(a, SymbolStatsEstimate.builder().setDistinctValuesCount(20).build()) .addSymbolStatistics(b, SymbolStatsEstimate.builder().setDistinctValuesCount(30).build()) .addSymbolStatistics(c, SymbolStatsEstimate.unknown()) .build(); PlanNodeStatsAssertion.assertThat(normalizer.normalize(estimate, ImmutableList.of(b, c), TypeProvider.copyOf(ImmutableMap.of(b, BIGINT, c, BIGINT)))) .symbolsWithKnownStats(b) .symbolStats(b, symbolAssert -> symbolAssert.distinctValuesCount(30)); }
@Test public void testSymbolReference() { SymbolStatsEstimate xStats = SymbolStatsEstimate.builder() .setLowValue(-1) .setHighValue(10) .setDistinctValuesCount(4) .setNullsFraction(0.1) .setAverageRowSize(2.0) .build(); PlanNodeStatsEstimate inputStatistics = PlanNodeStatsEstimate.builder() .addSymbolStatistics(new Symbol("x"), xStats) .build(); assertCalculate(expression("x"), inputStatistics).isEqualTo(xStats); assertCalculate(expression("y"), inputStatistics).isEqualTo(SymbolStatsEstimate.unknown()); }
@Test public void tesCapDistinctValuesByOutputRowCount() { Symbol a = new Symbol("a"); Symbol b = new Symbol("b"); Symbol c = new Symbol("c"); PlanNodeStatsEstimate estimate = PlanNodeStatsEstimate.builder() .addSymbolStatistics(a, SymbolStatsEstimate.builder().setNullsFraction(0).setDistinctValuesCount(20).build()) .addSymbolStatistics(b, SymbolStatsEstimate.builder().setNullsFraction(0.4).setDistinctValuesCount(20).build()) .addSymbolStatistics(c, SymbolStatsEstimate.unknown()) .setOutputRowCount(10) .build(); assertNormalized(estimate) .symbolStats(a, symbolAssert -> symbolAssert.distinctValuesCount(10)) .symbolStats(b, symbolAssert -> symbolAssert.distinctValuesCount(8)) .symbolStats(c, SymbolStatsAssertion::distinctValuesCountUnknown); }
.setOutputRowCount(20) .addSymbolStatistics(new Symbol("x"), xStats) .addSymbolStatistics(new Symbol("y"), SymbolStatsEstimate.unknown()) .build()) .check(PlanNodeStatsAssertion::outputRowsCountUnknown);
.addSymbolStatistics(unknownRange, unknownRangeStats) .addSymbolStatistics(emptyRange, emptyRangeStats) .addSymbolStatistics(unknown, SymbolStatsEstimate.unknown()) .addSymbolStatistics(fractionalNdv, fractionalNdvStats) .setOutputRowCount(1000.0)