package com.taobao.tddl.optimizer.costbased;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import com.taobao.tddl.common.model.ExtraCmd;
import com.taobao.tddl.optimizer.BaseOptimizerTest;
import com.taobao.tddl.optimizer.core.ast.QueryTreeNode;
import com.taobao.tddl.optimizer.core.ast.query.JoinNode;
import com.taobao.tddl.optimizer.core.ast.query.KVIndexNode;
import com.taobao.tddl.optimizer.core.ast.query.MergeNode;
import com.taobao.tddl.optimizer.core.ast.query.QueryNode;
import com.taobao.tddl.optimizer.costbased.chooser.DataNodeChooser;
public class DataNodeChooserTest extends BaseOptimizerTest {
@Test
public void test_单表查询_不生成merge() {
KVIndexNode table7 = new KVIndexNode("TABLE7");
table7.build();
QueryTreeNode qtn = shard(table7, false, false);
Assert.assertTrue(qtn instanceof KVIndexNode);
Assert.assertEquals("andor_group_0", qtn.getDataNode());
Assert.assertEquals("table7", ((KVIndexNode) qtn).getActualTableName());
}
@Test
public void test_单表查询_生成merge() {
KVIndexNode table7 = new KVIndexNode("TABLE1");
table7.build();
QueryTreeNode qtn = shard(table7, false, false);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(8, qtn.getChildren().size());
}
@Test
public void test_子查询_不生成merge() {
KVIndexNode table7 = new KVIndexNode("TABLE7");
table7.build();
QueryNode query = new QueryNode(table7);
QueryTreeNode qtn = shard(query, false, false);
Assert.assertTrue(qtn instanceof QueryNode);
Assert.assertEquals("andor_group_0", qtn.getDataNode());
Assert.assertEquals("andor_group_0", qtn.getChild().getDataNode());
Assert.assertEquals("table7", ((KVIndexNode) qtn.getChild()).getActualTableName());
}
@Test
public void test_子查询_生成merge() {
KVIndexNode table7 = new KVIndexNode("TABLE1");
table7.build();
QueryNode query = new QueryNode(table7);
QueryTreeNode qtn = shard(query, false, false);
// Merge的query
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertTrue(qtn.getChild() instanceof QueryNode);
Assert.assertEquals(8, qtn.getChildren().size());
}
@Test
public void test_子查询_不生成merge_存在聚合查询() {
KVIndexNode table7 = new KVIndexNode("TABLE1");
table7.limit(0, 1);
table7.build();
QueryNode query = new QueryNode(table7);
QueryTreeNode qtn = shard(query, false, false);
Assert.assertTrue(qtn instanceof QueryNode);
Assert.assertTrue(qtn.getChild() instanceof MergeNode);
Assert.assertEquals(8, ((MergeNode) qtn.getChild()).getChildren().size());
}
@Test
public void test_join查询_不生成merge() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
table1.keyQuery("ID = 1");
KVIndexNode table2 = new KVIndexNode("TABLE2");
table2.keyQuery("ID = 1");
JoinNode join = table1.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, false);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertEquals("andor_group_0", ((JoinNode) qtn).getLeftNode().getDataNode());
Assert.assertEquals("andor_group_0", ((JoinNode) qtn).getRightNode().getDataNode());
Assert.assertEquals("table1_01", ((KVIndexNode) ((JoinNode) qtn).getLeftNode()).getActualTableName());
Assert.assertEquals("table2_01", ((KVIndexNode) ((JoinNode) qtn).getRightNode()).getActualTableName());
}
@Test
public void test_join查询_生成MergeJoinMerge_没设置条件全表扫描() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
KVIndexNode table2 = new KVIndexNode("TABLE2");
JoinNode join = table1.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, false);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof MergeNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
Assert.assertEquals(8, ((JoinNode) qtn).getLeftNode().getChildren().size());
Assert.assertEquals(1, ((JoinNode) qtn).getRightNode().getChildren().size());// 右边是一个未决节点
}
@Test
public void test_join查询_生成JoinMergeJoin_设置filter局部表join_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
table1.keyQuery("TABLE1.ID IN (1,2,3)");
KVIndexNode table2 = new KVIndexNode("TABLE2");
table2.keyQuery("TABLE2.ID IN (1,2,3)");
JoinNode join = table1.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(3, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
}
@Test
public void test_join查询_生成JoinMergeJoin_没设置条件全表扫描_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
KVIndexNode table2 = new KVIndexNode("TABLE2");
JoinNode join = table1.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(8, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
}
@Test
public void test_join查询_不生成JoinMergeJoin_join条件不是分区字段_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
KVIndexNode table2 = new KVIndexNode("TABLE2");
JoinNode join = table1.join(table2, "NAME", "NAME");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof JoinNode); // 不做join merge join优化
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof MergeNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
Assert.assertEquals(8, ((JoinNode) qtn).getLeftNode().getChildren().size());
Assert.assertEquals(1, ((JoinNode) qtn).getRightNode().getChildren().size());// 右边是一个未决节点
}
@Test
public void test_join查询_生成JoinMergeJoin_嵌套子查询和Join带条件局部join_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
table1.alias("A");
QueryNode query1 = new QueryNode(table1);
query1.select("A.ID AS AID , A.NAME AS ANAME , A.SCHOOL AS ASCHOOL");
KVIndexNode table2 = new KVIndexNode("TABLE2");
table2.alias("B");
QueryNode query2 = new QueryNode(table2);
query2.select("B.ID AS BID , B.NAME AS BNAME , B.SCHOOL AS BSCHOOL");
JoinNode join = query1.join(query2, "AID", "BID");// 用的是子表的别名
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(8, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
Assert.assertTrue(((JoinNode) qtn.getChild()).getChild() instanceof QueryNode);
}
@Test
public void test_join查询_生成JoinMergeJoin_嵌套子查询全表扫描_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
table1.keyQuery("TABLE1.ID IN (1,2,3)");
table1.alias("A");
QueryNode query1 = new QueryNode(table1);
query1.select("A.ID AS AID , A.NAME AS ANAME , A.SCHOOL AS ASCHOOL");
KVIndexNode table2 = new KVIndexNode("TABLE2");
table2.keyQuery("TABLE2.ID IN (1,2,3)");
KVIndexNode table3 = new KVIndexNode("TABLE3");
table3.keyQuery("TABLE3.ID IN (1,2,3)");
JoinNode join = table2.join(table3, "ID", "ID");
// 两层join,左边是query,右边是join
JoinNode nextJoin = query1.join(join, "AID", "TABLE2.ID");// 用的是子表的别名
nextJoin.build();
QueryTreeNode qtn = shard(nextJoin, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(3, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
Assert.assertTrue(((JoinNode) qtn.getChild()).getLeftNode() instanceof QueryNode);
Assert.assertTrue(((JoinNode) qtn.getChild()).getRightNode() instanceof JoinNode);
}
@Test
public void test_join查询_不生成JoinMergeJoin_嵌套子查询全表扫描_存在聚合查询_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");
table1.keyQuery("TABLE1.ID IN (1,2,3)");
table1.alias("A");
table1.limit(0, 1);// 需要聚合操作
QueryNode query1 = new QueryNode(table1);
query1.select("A.ID AS AID , A.NAME AS ANAME , A.SCHOOL AS ASCHOOL");
KVIndexNode table2 = new KVIndexNode("TABLE2");
table2.keyQuery("TABLE2.ID IN (1,2,3)");
KVIndexNode table3 = new KVIndexNode("TABLE3");
table3.keyQuery("TABLE3.ID IN (1,2,3)");
JoinNode join = table2.join(table3, "ID", "ID");
// 两层join,左边是query,右边是join
JoinNode nextJoin = query1.join(join, "AID", "TABLE2.ID");// 用的是子表的别名
nextJoin.build();
QueryTreeNode qtn = shard(nextJoin, false, true);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof QueryNode);
Assert.assertEquals(3, ((MergeNode) ((JoinNode) qtn).getLeftNode().getChild()).getChildren().size());
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
}
@Test
public void test_join查询_不生成JoinMergeJoin_左边是不是Merge_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE8");// 这是一个单表,不分库
table1.keyQuery("TABLE8.ID IN (1,2,3)");
KVIndexNode table2 = new KVIndexNode("TABLE2");// 分库表
table2.keyQuery("TABLE2.ID IN (1,2,3)");
JoinNode join = table1.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof KVIndexNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
Assert.assertEquals(1, ((JoinNode) qtn).getRightNode().getChildren().size());// 因为是个未决节点
}
@Test
public void test_join查询_不生成JoinMergeJoin_左边是不是Merge_右边是子查询_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE8");// 这是一个单表,不分库
table1.keyQuery("TABLE8.ID IN (1,2,3)");
KVIndexNode table2 = new KVIndexNode("TABLE2");// 分库表
table2.keyQuery("TABLE2.ID IN (1,2,3)");
QueryNode query = new QueryNode(table2);
query.setSubQuery(true); // 是个子查询,会进行BLOCK_NEST_LOOP处理,就不需要未决节点进行mget处理
JoinNode join = table1.join(query, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof KVIndexNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode().getChild() instanceof QueryNode);
Assert.assertEquals(3, ((JoinNode) qtn).getRightNode().getChildren().size());// 是个子查询的Merge
}
@Test
public void test_join查询_不生成JoinMergeJoin_左右分区结果不一致_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");// 这是一个单表,不分库
table1.keyQuery("TABLE1.ID IN (2,3,4)");
KVIndexNode table2 = new KVIndexNode("TABLE2");// 分库表
table2.keyQuery("TABLE2.ID IN (1,2,3)");
JoinNode join = table1.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof MergeNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
Assert.assertEquals(3, ((JoinNode) qtn).getLeftNode().getChildren().size());
Assert.assertEquals(1, ((JoinNode) qtn).getRightNode().getChildren().size());// 未决节点
}
@Test
public void test_join查询_生成JoinMergeJoin_左边是广播表_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE7");// 这是一个广播表
QueryNode query = new QueryNode(table1);
KVIndexNode table2 = new KVIndexNode("TABLE2");// 分库表
JoinNode join = query.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(8, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
Assert.assertTrue(((JoinNode) qtn.getChild()).getLeftNode() instanceof QueryNode);
Assert.assertTrue(((JoinNode) qtn.getChild()).getRightNode() instanceof KVIndexNode);
}
@Test
public void test_join查询_生成JoinMergeJoin_右边是广播表_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");// 分库表
QueryNode query = new QueryNode(table1);
KVIndexNode table2 = new KVIndexNode("TABLE7");// 这是一个广播表
JoinNode join = query.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(8, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
Assert.assertTrue(((JoinNode) qtn.getChild()).getLeftNode() instanceof QueryNode);
Assert.assertTrue(((JoinNode) qtn.getChild()).getRightNode() instanceof KVIndexNode);
}
@Test
public void test_join查询_不生成JoinMergeJoin_左右都是广播表_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE7");// 这是一个广播表
table1.alias("A");
QueryNode query = new QueryNode(table1);
KVIndexNode table2 = new KVIndexNode("TABLE7");// 这是一个广播表
table2.alias("B");
JoinNode join = query.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof QueryNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof KVIndexNode);
}
@Test
public void test_join查询_不生成JoinMergeJoin_不同的joinGroup_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE1");// 分库表
QueryNode query = new QueryNode(table1);
KVIndexNode table2 = new KVIndexNode("TABLE5");// 这是一个广播表
JoinNode join = query.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof JoinNode);
Assert.assertTrue(((JoinNode) qtn).getLeftNode() instanceof MergeNode);
Assert.assertTrue(((JoinNode) qtn).getRightNode() instanceof MergeNode);
Assert.assertEquals(8, ((JoinNode) qtn).getLeftNode().getChildren().size());
Assert.assertEquals(1, ((JoinNode) qtn).getRightNode().getChildren().size());// 未决节点
}
@Test
public void test_join查询_生成JoinMergeJoin_左右joinGroup都是other_开启优化参数() {
KVIndexNode table1 = new KVIndexNode("TABLE5");// 分库表
QueryNode query = new QueryNode(table1);
KVIndexNode table2 = new KVIndexNode("TABLE6");// 这是一个广播表
JoinNode join = query.join(table2, "ID", "ID");
join.build();
QueryTreeNode qtn = shard(join, false, true);
Assert.assertTrue(qtn instanceof MergeNode);
Assert.assertEquals(4, qtn.getChildren().size());
Assert.assertTrue(qtn.getChild() instanceof JoinNode);// join merge join
Assert.assertTrue(((JoinNode) qtn.getChild()).getLeftNode() instanceof QueryNode);
Assert.assertTrue(((JoinNode) qtn.getChild()).getRightNode() instanceof KVIndexNode);
}
private QueryTreeNode shard(QueryTreeNode qtn, boolean joinMergeJoin, boolean joinMergeJoinByRule) {
Map<String, Object> extraCmd = new HashMap<String, Object>();
extraCmd.put(ExtraCmd.JOIN_MERGE_JOIN, joinMergeJoin);
extraCmd.put(ExtraCmd.JOIN_MERGE_JOIN_JUDGE_BY_RULE, joinMergeJoinByRule);
return (QueryTreeNode) DataNodeChooser.shard(qtn, null, extraCmd);
}
}