use of org.apache.ignite.internal.sql.engine.rel.IgniteExchange in project ignite-3 by apache.
the class JoinColocationPlannerTest method joinComplexToComplexAffWithDifferentOrder.
/**
* Re-hashing for complex affinity is not supported.
*/
@Test
public void joinComplexToComplexAffWithDifferentOrder() throws Exception {
TestTable complexTblDirect = createTable("COMPLEX_TBL_DIRECT", IgniteDistributions.affinity(ImmutableIntList.of(0, 1), ThreadLocalRandom.current().nextInt(), "hash"), "ID1", Integer.class, "ID2", Integer.class, "VAL", String.class);
complexTblDirect.addIndex(new IgniteIndex(RelCollations.of(ImmutableIntList.of(0, 1)), "PK", complexTblDirect));
TestTable complexTblIndirect = createTable("COMPLEX_TBL_INDIRECT", IgniteDistributions.affinity(ImmutableIntList.of(1, 0), ThreadLocalRandom.current().nextInt(), "hash"), "ID1", Integer.class, "ID2", Integer.class, "VAL", String.class);
complexTblIndirect.addIndex(new IgniteIndex(RelCollations.of(ImmutableIntList.of(0, 1)), "PK", complexTblIndirect));
IgniteSchema schema = createSchema(complexTblDirect, complexTblIndirect);
String sql = "select count(*) " + "from COMPLEX_TBL_DIRECT t1 " + "join COMPLEX_TBL_INDIRECT t2 on t1.id1 = t2.id1 and t1.id2 = t2.id2";
RelNode phys = physicalPlan(sql, schema, "NestedLoopJoinConverter", "CorrelatedNestedLoopJoin");
IgniteMergeJoin exchange = findFirstNode(phys, node -> node instanceof IgniteExchange && ((IgniteRel) node).distribution().function().affinity());
String invalidPlanMsg = "Invalid plan:\n" + RelOptUtil.toString(phys);
assertThat(invalidPlanMsg, exchange, nullValue());
}
use of org.apache.ignite.internal.sql.engine.rel.IgniteExchange in project ignite-3 by apache.
the class TraitUtils method convertDistribution.
/**
* Convert distribution. TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
*/
@Nullable
public static RelNode convertDistribution(RelOptPlanner planner, IgniteDistribution toTrait, RelNode rel) {
IgniteDistribution fromTrait = distribution(rel);
if (fromTrait.satisfies(toTrait)) {
return rel;
}
// key object, thus this conversion is impossible
if (toTrait.function().affinity() && toTrait.getKeys().size() > 1) {
return null;
}
RelTraitSet traits = rel.getTraitSet().replace(toTrait);
if (fromTrait.getType() == BROADCAST_DISTRIBUTED && toTrait.getType() == HASH_DISTRIBUTED) {
return new IgniteTrimExchange(rel.getCluster(), traits, rel, toTrait);
} else {
return new IgniteExchange(rel.getCluster(), traits.replace(RewindabilityTrait.ONE_WAY).replace(CorrelationTrait.UNCORRELATED), RelOptRule.convert(rel, rel.getTraitSet().replace(CorrelationTrait.UNCORRELATED)), toTrait);
}
}
use of org.apache.ignite.internal.sql.engine.rel.IgniteExchange in project ignite-3 by apache.
the class JoinColocationPlannerTest method joinComplexToSimpleAff.
/**
* Re-hashing based on simple affinity is possible, so bigger table with complex affinity should be sended to the smaller one.
*/
@Test
public void joinComplexToSimpleAff() throws Exception {
TestTable complexTbl = createTable("COMPLEX_TBL", 2 * DEFAULT_TBL_SIZE, IgniteDistributions.affinity(ImmutableIntList.of(0, 1), ThreadLocalRandom.current().nextInt(), "hash"), "ID1", Integer.class, "ID2", Integer.class, "VAL", String.class);
complexTbl.addIndex(new IgniteIndex(RelCollations.of(ImmutableIntList.of(0, 1)), "PK", complexTbl));
TestTable simpleTbl = createTable("SIMPLE_TBL", DEFAULT_TBL_SIZE, IgniteDistributions.affinity(0, "default", "hash"), "ID", Integer.class, "VAL", String.class);
simpleTbl.addIndex(new IgniteIndex(RelCollations.of(0), "PK", simpleTbl));
IgniteSchema schema = createSchema(complexTbl, simpleTbl);
String sql = "select count(*) " + "from COMPLEX_TBL t1 " + "join SIMPLE_TBL t2 on t1.id1 = t2.id";
RelNode phys = physicalPlan(sql, schema, "NestedLoopJoinConverter", "CorrelatedNestedLoopJoin");
IgniteMergeJoin join = findFirstNode(phys, byClass(IgniteMergeJoin.class));
String invalidPlanMsg = "Invalid plan:\n" + RelOptUtil.toString(phys);
assertThat(invalidPlanMsg, join, notNullValue());
assertThat(invalidPlanMsg, join.distribution().function().affinity(), is(true));
List<IgniteExchange> exchanges = findNodes(phys, node -> node instanceof IgniteExchange && ((IgniteRel) node).distribution().function().affinity());
assertThat(invalidPlanMsg, exchanges, hasSize(1));
assertThat(invalidPlanMsg, exchanges.get(0).getInput(0), instanceOf(IgniteIndexScan.class));
assertThat(invalidPlanMsg, exchanges.get(0).getInput(0).getTable().unwrap(TestTable.class), equalTo(complexTbl));
}
use of org.apache.ignite.internal.sql.engine.rel.IgniteExchange in project ignite-3 by apache.
the class IgniteMdFragmentMapping method fragmentMapping.
/**
* See {@link IgniteMdFragmentMapping#fragmentMapping(RelNode, RelMetadataQuery, MappingQueryContext)}.
*
* <p>{@link ColocationMappingException} may be thrown on two children nodes locations merge. This means that the fragment
* (which part the parent node is) cannot be executed on any node and additional exchange is needed. This case we throw {@link
* NodeMappingException} with an edge, where we need the additional exchange. After the exchange is put into the fragment and the
* fragment is split into two ones, fragment meta information will be recalculated for all fragments.
*/
public FragmentMapping fragmentMapping(BiRel rel, RelMetadataQuery mq, MappingQueryContext ctx) {
RelNode left = rel.getLeft();
RelNode right = rel.getRight();
FragmentMapping frgLeft = fragmentMappingForMetadataQuery(left, mq, ctx);
FragmentMapping frgRight = fragmentMappingForMetadataQuery(right, mq, ctx);
try {
return frgLeft.colocate(frgRight);
} catch (ColocationMappingException e) {
IgniteExchange leftExch = new IgniteExchange(rel.getCluster(), left.getTraitSet(), left, TraitUtils.distribution(left));
IgniteExchange rightExch = new IgniteExchange(rel.getCluster(), right.getTraitSet(), right, TraitUtils.distribution(right));
RelNode leftVar = rel.copy(rel.getTraitSet(), List.of(leftExch, right));
RelNode rightVar = rel.copy(rel.getTraitSet(), List.of(left, rightExch));
RelOptCost leftVarCost = mq.getCumulativeCost(leftVar);
RelOptCost rightVarCost = mq.getCumulativeCost(rightVar);
if (leftVarCost.isLt(rightVarCost)) {
throw new NodeMappingException("Failed to calculate physical distribution", left, e);
} else {
throw new NodeMappingException("Failed to calculate physical distribution", right, e);
}
}
}
Aggregations