/** 把query中的avg换成count,sum */ @Override public IDataNodeExecutor optimize( IDataNodeExecutor dne, Map<Integer, ParameterContext> parameterSettings, Map<String, Object> extraCmd) { if (dne instanceof IMerge && ((IMerge) dne).getSubNode().size() > 1) { for (IDataNodeExecutor sub : ((IMerge) dne).getSubNode()) { expendAvgFunction(sub); } for (IDataNodeExecutor sub : ((IMerge) dne).getSubNode()) { this.optimize(sub, parameterSettings, extraCmd); } } else if (dne instanceof IJoin) { IJoin join = (IJoin) dne; // join函数,采取map模式,不需要处理avg展开 // 递归处理子节点 this.optimize(join.getLeftNode(), parameterSettings, extraCmd); this.optimize(join.getRightNode(), parameterSettings, extraCmd); } else if (dne instanceof IQuery) { IQuery query = (IQuery) dne; // 如果是子查询,采取map模式,不需要处理avg展开 if (query.isSubQuery()) { this.optimize(query.getSubQuery(), parameterSettings, extraCmd); // 递归处理子节点 } } return dne; }
@Override public IBlockNestedLoopCursor blockNestedLoopJoinCursor( ExecutionContext executionContext, ISchematicCursor left_cursor, ISchematicCursor right_cursor, List left_columns, List right_columns, List columns, IJoin join) throws TddlException { try { return new BlockNestedtLoopCursor( left_cursor, right_cursor, left_columns, right_columns, columns, this, join, executionContext, join.getLeftNode().getColumns(), join.getRightNode().getColumns()); } catch (Exception e) { closeParentCursor(left_cursor); closeParentCursor(right_cursor); throw new TddlException(e); } }
@Override public IIndexNestLoopCursor indexNestLoopCursor( ExecutionContext executionContext, ISchematicCursor leftCursor, ISchematicCursor rightCursor, List leftColumns, List rightColumns, List columns, boolean prefix, IJoin executor) throws TddlException { try { return new IndexNestedLoopMgetImpCursor( leftCursor, rightCursor, leftColumns, rightColumns, columns, prefix, executor.getLeftNode().getColumns(), executor.getRightNode().getColumns(), executor, executionContext); } catch (Exception e) { closeParentCursor(leftCursor); closeParentCursor(rightCursor); throw new TddlException(e); } }
// 两表Join查询,右表连接键为主键,右表为主键查询 // 开启了join merge join // 右表主键索引的查询,Join列也索引列,应该选择IndexNestLoop // 会是一个(table1 join table2 index ) join table2 key 的多级join @Test public void test_两表Join_主键索引_存在主键索引条件() { TableNode table = new TableNode("TABLE1"); JoinNode join = table.join("TABLE2", "ID", "ID"); join.query("TABLE2.ID IN (1,2)"); IQueryTree qc = (IQueryTree) optimizer.optimizeAndAssignment(join, null, extraCmd); Assert.assertTrue(qc instanceof IMerge); Assert.assertTrue(((IMerge) qc).getSubNodes().get(0) instanceof IJoin); IJoin subJoin = (IJoin) ((IMerge) qc).getSubNodes().get(0); Assert.assertEquals(JoinStrategy.INDEX_NEST_LOOP, subJoin.getJoinStrategy()); }
@Test public void test_两表join_单独limit条件_不做并行() { TableNode table = new TableNode("TABLE1"); JoinNode join = table.join("TABLE2", "ID", "ID"); join.select( OptimizerUtils.createColumnFromString("TABLE1.ID AS JID"), OptimizerUtils.createColumnFromString("CONCAT(TABLE1.NAME,TABLE1.SCHOOL) AS JNAME")); join.limit(10, 20); IQueryTree qc = (IQueryTree) optimizer.optimizeAndAssignment(join, null, extraCmd); Assert.assertTrue(qc instanceof IMerge); Assert.assertEquals(QUERY_CONCURRENCY.SEQUENTIAL, ((IMerge) qc).getQueryConcurrency()); // 串行 IJoin jn = (IJoin) ((IMerge) qc).getSubNodes().get(0); Assert.assertEquals("0", jn.getLimitFrom().toString()); Assert.assertEquals("30", jn.getLimitTo().toString()); }
// 两表Join查询,右表连接键为主键,右表为二级索引查询 // 开启了join merge join // 右表二级索引的查询,Join列也是二级索引索引,应该选择NestLoop // 会是一个(table1 index join table1 index ) join (table2 index join table2 // key)的多级join @Test public void test_两表Join_二级索引_存在二级索引条件() { TableNode table = new TableNode("TABLE1"); JoinNode join = table.join("TABLE2", "NAME", "NAME"); join.query("TABLE2.NAME = 1"); IQueryTree qc = (IQueryTree) optimizer.optimizeAndAssignment(join, null, extraCmd); Assert.assertTrue(qc instanceof IJoin); Assert.assertTrue(((IJoin) qc).getLeftNode() instanceof IJoin); Assert.assertTrue(((IJoin) qc).getRightNode() instanceof IMerge); Assert.assertEquals(JoinStrategy.INDEX_NEST_LOOP, ((IJoin) qc).getJoinStrategy()); IJoin subJoin = (IJoin) ((IJoin) qc).getLeftNode(); Assert.assertTrue(((IJoin) subJoin).getLeftNode() instanceof IMerge); Assert.assertTrue(((IJoin) subJoin).getRightNode() instanceof IMerge); Assert.assertEquals(JoinStrategy.INDEX_NEST_LOOP, subJoin.getJoinStrategy()); }
// 单表非主键索引查询 // NAME上存在索引 // 会生成一个Join节点 // 左边通过NAME索引找到满足条件的PK,keyFilter应该为NAME=1 // 与pk->data Join // Join类型为IndexNestLoop @Test public void test_单表查询_value条件() { TableNode table = new TableNode("TABLE1"); table.query("NAME = 1"); IQueryTree qc = (IQueryTree) optimizer.optimizeAndAssignment(table, null, extraCmd); Assert.assertTrue(qc instanceof IMerge); Assert.assertEquals( QUERY_CONCURRENCY.GROUP_CONCURRENT, ((IMerge) qc).getQueryConcurrency()); // 并行 IDataNodeExecutor dne = ((IMerge) qc).getSubNodes().get(0); Assert.assertTrue(dne instanceof IJoin); IJoin join = (IJoin) dne; IQuery left = (IQuery) join.getLeftNode(); Assert.assertEquals("TABLE1._NAME.NAME = 1", left.getKeyFilter().toString()); }
// 单表or查询 // 查询条件由or连接, // 由于NAME和ID上存在索引,所以会生成两个子查询 // or的两边分别作为子查询的keyFilter // 由于NAME=2323的子查询为非主键索引查询 // 所以此处会生成一个join节点 // 最后一个merge节点用于合并子查询的结果 @Test public void test_单表查询_OR条件_1() { TableNode table = new TableNode("TABLE1"); table.query("NAME = 2323 OR ID=1"); extraCmd.put(ConnectionProperties.CHOOSE_INDEX_MERGE, true); IQueryTree qc = (IQueryTree) optimizer.optimizeAndAssignment(table, null, extraCmd); extraCmd.put(ConnectionProperties.CHOOSE_INDEX_MERGE, false); Assert.assertTrue(qc instanceof IMerge); Assert.assertTrue(((IMerge) qc).isUnion()); // 是union查询 Assert.assertTrue(((IMerge) qc).getSubNodes().get(0) instanceof IQuery); IQuery query = (IQuery) ((IMerge) qc).getSubNodes().get(0); Assert.assertEquals("TABLE1.ID = 1", query.getKeyFilter().toString()); Assert.assertTrue(((IMerge) qc).getSubNodes().get(1) instanceof IMerge); Assert.assertTrue( ((IMerge) ((IMerge) qc).getSubNodes().get(1)).getSubNodes().get(0) instanceof IJoin); IJoin join = (IJoin) ((IMerge) ((IMerge) qc).getSubNodes().get(1)).getSubNodes().get(0); Assert.assertEquals( "TABLE1._NAME.NAME = 2323", ((IQuery) join.getLeftNode()).getKeyFilter().toString()); }