@Override protected Optional<PlanNodeStatsEstimate> doCalculate(ExchangeNode node, StatsProvider statsProvider, Lookup lookup, Session session, TypeProvider types) { Optional<PlanNodeStatsEstimate> estimate = Optional.empty(); for (int i = 0; i < node.getSources().size(); i++) { PlanNode source = node.getSources().get(i); PlanNodeStatsEstimate sourceStats = statsProvider.getStats(source); PlanNodeStatsEstimate sourceStatsWithMappedSymbols = mapToOutputSymbols(sourceStats, node.getInputs().get(i), node.getOutputSymbols()); if (estimate.isPresent()) { estimate = Optional.of(addStatsAndMaxDistinctValues(estimate.get(), sourceStatsWithMappedSymbols)); } else { estimate = Optional.of(sourceStatsWithMappedSymbols); } } verify(estimate.isPresent()); return estimate; }
public static PlanNodeStatsEstimate addStatsAndSumDistinctValues(PlanNodeStatsEstimate left, PlanNodeStatsEstimate right) { return addStats(left, right, StatisticRange::addAndSumDistinctValues); }
@Override protected final Optional<PlanNodeStatsEstimate> doCalculate(UnionNode node, StatsProvider statsProvider, Lookup lookup, Session session, TypeProvider types) { checkArgument(!node.getSources().isEmpty(), "Empty Union is not supported"); Optional<PlanNodeStatsEstimate> estimate = Optional.empty(); for (int i = 0; i < node.getSources().size(); i++) { PlanNode source = node.getSources().get(i); PlanNodeStatsEstimate sourceStats = statsProvider.getStats(source); PlanNodeStatsEstimate sourceStatsWithMappedSymbols = mapToOutputSymbols(sourceStats, node.getSymbolMapping(), i); if (estimate.isPresent()) { estimate = Optional.of(addStatsAndCollapseDistinctValues(estimate.get(), sourceStatsWithMappedSymbols)); } else { estimate = Optional.of(sourceStatsWithMappedSymbols); } } return estimate; }
private PlanNodeStatsEstimate estimateLogicalOr(Expression left, Expression right) { PlanNodeStatsEstimate leftEstimate = process(left); if (leftEstimate.isOutputRowCountUnknown()) { return PlanNodeStatsEstimate.unknown(); } PlanNodeStatsEstimate rightEstimate = process(right); if (rightEstimate.isOutputRowCountUnknown()) { return PlanNodeStatsEstimate.unknown(); } PlanNodeStatsEstimate andEstimate = new FilterExpressionStatsCalculatingVisitor(leftEstimate, session, types).process(right); if (andEstimate.isOutputRowCountUnknown()) { return PlanNodeStatsEstimate.unknown(); } return capStats( subtractSubsetStats( addStatsAndSumDistinctValues(leftEstimate, rightEstimate), andEstimate), input); }
private static void assertSubtractNumberOfDistinctValues(PlanNodeStatsEstimate first, PlanNodeStatsEstimate second, double expected) { assertEquals(subtractSubsetStats(first, second).getSymbolStatistics(SYMBOL).getDistinctValuesCount(), expected); }
@Test public void testCapRowCount() { PlanNodeStatsEstimate unknownRowCount = statistics(NaN, NaN, NaN, NON_EMPTY_RANGE); PlanNodeStatsEstimate first = statistics(20, NaN, NaN, NON_EMPTY_RANGE); PlanNodeStatsEstimate second = statistics(10, NaN, NaN, NON_EMPTY_RANGE); assertEquals(capStats(unknownRowCount, unknownRowCount).getOutputRowCount(), NaN); assertEquals(capStats(first, unknownRowCount).getOutputRowCount(), NaN); assertEquals(capStats(unknownRowCount, second).getOutputRowCount(), NaN); assertEquals(capStats(first, second).getOutputRowCount(), 10.0); assertEquals(capStats(second, first).getOutputRowCount(), 10.0); }
private static void assertSumNumberOfDistinctValues(PlanNodeStatsEstimate first, PlanNodeStatsEstimate second, double expected) { assertEquals(addStatsAndSumDistinctValues(first, second).getSymbolStatistics(SYMBOL).getDistinctValuesCount(), expected); }
private static PlanNodeStatsEstimate addStats(PlanNodeStatsEstimate left, PlanNodeStatsEstimate right, RangeAdditionStrategy strategy) { if (left.isOutputRowCountUnknown() || right.isOutputRowCountUnknown()) { return PlanNodeStatsEstimate.unknown(); } PlanNodeStatsEstimate.Builder statsBuilder = PlanNodeStatsEstimate.builder(); double newRowCount = left.getOutputRowCount() + right.getOutputRowCount(); concat(left.getSymbolsWithKnownStatistics().stream(), right.getSymbolsWithKnownStatistics().stream()) .distinct() .forEach(symbol -> { SymbolStatsEstimate symbolStats = SymbolStatsEstimate.zero(); if (newRowCount > 0) { symbolStats = addColumnStats( left.getSymbolStatistics(symbol), left.getOutputRowCount(), right.getSymbolStatistics(symbol), right.getOutputRowCount(), newRowCount, strategy); } statsBuilder.addSymbolStatistics(symbol, symbolStats); }); return statsBuilder.setOutputRowCount(newRowCount).build(); }
return createZeroStats(superset);
@Override protected PlanNodeStatsEstimate visitNotExpression(NotExpression node, Void context) { if (node.getValue() instanceof IsNullPredicate) { return process(new IsNotNullPredicate(((IsNullPredicate) node.getValue()).getValue())); } return subtractSubsetStats(input, process(node.getValue())); }
private static void assertCapAverageRowSize(PlanNodeStatsEstimate stats, PlanNodeStatsEstimate cap, double expected) { assertEquals(capStats(stats, cap).getSymbolStatistics(SYMBOL).getAverageRowSize(), expected); }
private static void assertAddNullsFraction(PlanNodeStatsEstimate first, PlanNodeStatsEstimate second, double expected) { assertEquals(addStatsAndSumDistinctValues(first, second).getSymbolStatistics(SYMBOL).getNullsFraction(), expected); }
@Test public void testSubtractRowCount() { PlanNodeStatsEstimate unknownStats = statistics(NaN, NaN, NaN, StatisticRange.empty()); PlanNodeStatsEstimate first = statistics(40, NaN, NaN, StatisticRange.empty()); PlanNodeStatsEstimate second = statistics(10, NaN, NaN, StatisticRange.empty()); assertEquals(subtractSubsetStats(unknownStats, unknownStats), PlanNodeStatsEstimate.unknown()); assertEquals(subtractSubsetStats(first, unknownStats), PlanNodeStatsEstimate.unknown()); assertEquals(subtractSubsetStats(unknownStats, second), PlanNodeStatsEstimate.unknown()); assertEquals(subtractSubsetStats(first, second).getOutputRowCount(), 30.0); }
private static void assertCapNumberOfDistinctValues(PlanNodeStatsEstimate stats, PlanNodeStatsEstimate cap, double expected) { assertEquals(capStats(stats, cap).getSymbolStatistics(SYMBOL).getDistinctValuesCount(), expected); }
private static void assertAddAverageRowSize(PlanNodeStatsEstimate first, PlanNodeStatsEstimate second, double expected) { assertEquals(addStatsAndSumDistinctValues(first, second).getSymbolStatistics(SYMBOL).getAverageRowSize(), expected); }
private static void assertMaxNumberOfDistinctValues(PlanNodeStatsEstimate first, PlanNodeStatsEstimate second, double expected) { assertEquals(addStatsAndMaxDistinctValues(first, second).getSymbolStatistics(SYMBOL).getDistinctValuesCount(), expected); }
public static PlanNodeStatsEstimate addStatsAndCollapseDistinctValues(PlanNodeStatsEstimate left, PlanNodeStatsEstimate right) { return addStats(left, right, StatisticRange::addAndCollapseDistinctValues); }
private static void assertSubtractNullsFraction(PlanNodeStatsEstimate first, PlanNodeStatsEstimate second, double expected) { assertEquals(subtractSubsetStats(first, second).getSymbolStatistics(SYMBOL).getNullsFraction(), expected); }
private static void assertCapNullsFraction(PlanNodeStatsEstimate stats, PlanNodeStatsEstimate cap, double expected) { assertEquals(capStats(stats, cap).getSymbolStatistics(SYMBOL).getNullsFraction(), expected); }
@Test public void testAddRowCount() { PlanNodeStatsEstimate unknownStats = statistics(NaN, NaN, NaN, StatisticRange.empty()); PlanNodeStatsEstimate first = statistics(10, NaN, NaN, StatisticRange.empty()); PlanNodeStatsEstimate second = statistics(20, NaN, NaN, StatisticRange.empty()); assertEquals(addStatsAndSumDistinctValues(unknownStats, unknownStats), PlanNodeStatsEstimate.unknown()); assertEquals(addStatsAndSumDistinctValues(first, unknownStats), PlanNodeStatsEstimate.unknown()); assertEquals(addStatsAndSumDistinctValues(unknownStats, second), PlanNodeStatsEstimate.unknown()); assertEquals(addStatsAndSumDistinctValues(first, second).getOutputRowCount(), 30.0); }