use of io.trino.sql.planner.plan.ExchangeNode in project trino by trinodb.
the class TestLogicalPlanner method testBroadcastCorrelatedSubqueryAvoidsRemoteExchangeBeforeAggregation.
@Test
public void testBroadcastCorrelatedSubqueryAvoidsRemoteExchangeBeforeAggregation() {
Session broadcastJoin = Session.builder(this.getQueryRunner().getDefaultSession()).setSystemProperty(JOIN_DISTRIBUTION_TYPE, JoinDistributionType.BROADCAST.name()).setSystemProperty(FORCE_SINGLE_NODE_OUTPUT, Boolean.toString(false)).build();
// make sure there is a remote exchange on the build side
PlanMatchPattern joinBuildSideWithRemoteExchange = anyTree(node(JoinNode.class, anyTree(node(TableScanNode.class)), anyTree(exchange(REMOTE, ExchangeNode.Type.REPLICATE, anyTree(node(TableScanNode.class))))));
// validates that there exists only one remote exchange
Consumer<Plan> validateSingleRemoteExchange = plan -> assertEquals(countOfMatchingNodes(plan, node -> node instanceof ExchangeNode && ((ExchangeNode) node).getScope() == REMOTE), 1);
Consumer<Plan> validateSingleStreamingAggregation = plan -> assertEquals(countOfMatchingNodes(plan, node -> node instanceof AggregationNode && ((AggregationNode) node).getGroupingKeys().contains(new Symbol("unique")) && ((AggregationNode) node).isStreamable()), 1);
// region is unpartitioned, AssignUniqueId should provide satisfying partitioning for count(*) after LEFT JOIN
assertPlanWithSession("SELECT (SELECT count(*) FROM region r2 WHERE r2.regionkey > r1.regionkey) FROM region r1", broadcastJoin, false, joinBuildSideWithRemoteExchange, validateSingleRemoteExchange.andThen(validateSingleStreamingAggregation));
// orders is naturally partitioned, AssignUniqueId should not overwrite its natural partitioning
assertPlanWithSession("SELECT count(count) " + "FROM (SELECT o1.orderkey orderkey, (SELECT count(*) FROM orders o2 WHERE o2.orderkey > o1.orderkey) count FROM orders o1) " + "GROUP BY orderkey", broadcastJoin, false, joinBuildSideWithRemoteExchange, validateSingleRemoteExchange.andThen(validateSingleStreamingAggregation));
}
use of io.trino.sql.planner.plan.ExchangeNode in project trino by trinodb.
the class ExchangeMatcher method detailMatches.
@Override
public MatchResult detailMatches(PlanNode node, StatsProvider stats, Session session, Metadata metadata, SymbolAliases symbolAliases) {
checkState(shapeMatches(node), "Plan testing framework error: shapeMatches returned false in detailMatches in %s", this.getClass().getName());
ExchangeNode exchangeNode = (ExchangeNode) node;
if (!orderBy.isEmpty()) {
if (exchangeNode.getOrderingScheme().isEmpty()) {
return NO_MATCH;
}
if (!orderingSchemeMatches(orderBy, exchangeNode.getOrderingScheme().get(), symbolAliases)) {
return NO_MATCH;
}
}
if (!partitionedBy.isEmpty()) {
Set<Symbol> partitionedColumns = exchangeNode.getPartitioningScheme().getPartitioning().getColumns();
if (!partitionedBy.stream().map(symbolAliases::get).map(Symbol::from).allMatch(partitionedColumns::contains)) {
return NO_MATCH;
}
}
if (inputs.isPresent()) {
if (inputs.get().size() != exchangeNode.getInputs().size()) {
return NO_MATCH;
}
for (int i = 0; i < exchangeNode.getInputs().size(); i++) {
if (!inputs.get().get(i).stream().map(symbolAliases::get).map(Symbol::from).collect(toImmutableList()).equals(exchangeNode.getInputs().get(i))) {
return NO_MATCH;
}
}
}
return MatchResult.match();
}
use of io.trino.sql.planner.plan.ExchangeNode in project trino by trinodb.
the class TestCostCalculator method testRepartitionedJoinWithExchange.
@Test
public void testRepartitionedJoinWithExchange() {
TableScanNode ts1 = tableScan("ts1", "orderkey");
TableScanNode ts2 = tableScan("ts2", "orderkey_0");
ExchangeNode remoteExchange1 = partitionedExchange(new PlanNodeId("re1"), REMOTE, ts1, ImmutableList.of(new Symbol("orderkey")), Optional.empty());
ExchangeNode remoteExchange2 = partitionedExchange(new PlanNodeId("re2"), REMOTE, ts2, ImmutableList.of(new Symbol("orderkey_0")), Optional.empty());
ExchangeNode localExchange = partitionedExchange(new PlanNodeId("le"), LOCAL, remoteExchange2, ImmutableList.of(new Symbol("orderkey_0")), Optional.empty());
JoinNode join = join("join", remoteExchange1, localExchange, JoinNode.DistributionType.PARTITIONED, "orderkey", "orderkey_0");
Map<String, PlanNodeStatsEstimate> stats = ImmutableMap.<String, PlanNodeStatsEstimate>builder().put("join", statsEstimate(join, 12000)).put("re1", statsEstimate(remoteExchange1, 10000)).put("re2", statsEstimate(remoteExchange2, 10000)).put("le", statsEstimate(localExchange, 6000)).put("ts1", statsEstimate(ts1, 6000)).put("ts2", statsEstimate(ts2, 1000)).buildOrThrow();
Map<String, Type> types = ImmutableMap.of("orderkey", BIGINT, "orderkey_0", BIGINT);
assertFragmentedEqualsUnfragmented(join, stats, types);
}
use of io.trino.sql.planner.plan.ExchangeNode in project trino by trinodb.
the class TestCostCalculator method testReplicatedJoinWithExchange.
@Test
public void testReplicatedJoinWithExchange() {
TableScanNode ts1 = tableScan("ts1", "orderkey");
TableScanNode ts2 = tableScan("ts2", "orderkey_0");
ExchangeNode remoteExchange2 = replicatedExchange(new PlanNodeId("re2"), REMOTE, ts2);
ExchangeNode localExchange = partitionedExchange(new PlanNodeId("le"), LOCAL, remoteExchange2, ImmutableList.of(new Symbol("orderkey_0")), Optional.empty());
JoinNode join = join("join", ts1, localExchange, JoinNode.DistributionType.REPLICATED, "orderkey", "orderkey_0");
Map<String, PlanNodeStatsEstimate> stats = ImmutableMap.<String, PlanNodeStatsEstimate>builder().put("join", statsEstimate(join, 12000)).put("re2", statsEstimate(remoteExchange2, 10000)).put("le", statsEstimate(localExchange, 6000)).put("ts1", statsEstimate(ts1, 6000)).put("ts2", statsEstimate(ts2, 1000)).buildOrThrow();
Map<String, Type> types = ImmutableMap.of("orderkey", BIGINT, "orderkey_0", BIGINT);
assertFragmentedEqualsUnfragmented(join, stats, types);
}
use of io.trino.sql.planner.plan.ExchangeNode in project trino by trinodb.
the class TestUnion method assertAtMostOneAggregationBetweenRemoteExchanges.
private static void assertAtMostOneAggregationBetweenRemoteExchanges(Plan plan) {
List<PlanNode> fragments = searchFrom(plan.getRoot()).where(TestUnion::isRemoteExchange).findAll().stream().flatMap(exchangeNode -> exchangeNode.getSources().stream()).collect(toList());
for (PlanNode fragment : fragments) {
List<PlanNode> aggregations = searchFrom(fragment).where(AggregationNode.class::isInstance).recurseOnlyWhen(TestUnion::isNotRemoteExchange).findAll();
assertFalse(aggregations.size() > 1, "More than a single AggregationNode between remote exchanges");
}
}
Aggregations