Repository: phoenix Updated Branches: refs/heads/4.x-HBase-0.98 1f4a5400b -> 7eac78e75
PHOENIX-2274 Sort-merge join could not optimize out the sort on the right table Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/ea91e634 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/ea91e634 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/ea91e634 Branch: refs/heads/4.x-HBase-0.98 Commit: ea91e634400a58654ba98d8b696c169272ac8308 Parents: 6cd7936 Author: maryannxue <wei....@intel.com> Authored: Mon Sep 21 09:26:07 2015 -0400 Committer: maryannxue <wei....@intel.com> Committed: Mon Sep 21 09:26:07 2015 -0400 ---------------------------------------------------------------------- .../apache/phoenix/end2end/SortMergeJoinIT.java | 35 ++++++++++++++++++-- .../end2end/SubqueryUsingSortMergeJoinIT.java | 2 -- .../apache/phoenix/compile/OrderByCompiler.java | 10 +++--- .../apache/phoenix/compile/QueryCompiler.java | 11 +++--- 4 files changed, 45 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/ea91e634/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java index 8b65ab3..9b85d8a 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java @@ -113,8 +113,6 @@ public class SortMergeJoinIT extends BaseHBaseManagedTimeIT { "AND\n" + " SORT-MERGE-JOIN (INNER) TABLES\n" + " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_DISPLAY_NAME + "\n" + - " SERVER SORTED BY [\"I.item_id\"]\n" + - " CLIENT MERGE SORT\n" + " AND (SKIP MERGE)\n" + " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" + " SERVER FILTER BY QUANTITY < 5000\n" + @@ -129,6 +127,12 @@ public class SortMergeJoinIT extends BaseHBaseManagedTimeIT { " SERVER SORTED BY [\"O.item_id\"]\n" + " CLIENT MERGE SORT\n" + "CLIENT 4 ROW LIMIT", + + "SORT-MERGE-JOIN (INNER) TABLES\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.ItemTable\n" + + "AND\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.ItemTable\n" + + " SERVER FILTER BY FIRST KEY ONLY" }}); testCases.add(new String[][] { { @@ -163,6 +167,18 @@ public class SortMergeJoinIT extends BaseHBaseManagedTimeIT { " SERVER SORTED BY [\"O.item_id\"]\n" + " CLIENT MERGE SORT\n" + "CLIENT 4 ROW LIMIT", + + "SORT-MERGE-JOIN (INNER) TABLES\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" + + " SERVER FILTER BY FIRST KEY ONLY\n" + + " SERVER SORTED BY [\"I1.:item_id\"]\n" + + " CLIENT MERGE SORT\n" + + "AND\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" + + " SERVER FILTER BY FIRST KEY ONLY\n" + + " SERVER SORTED BY [\"I2.:item_id\"]\n" + + " CLIENT MERGE SORT\n" + + "CLIENT SORTED BY [\"I1.:item_id\"]" }}); testCases.add(new String[][] { { @@ -197,6 +213,18 @@ public class SortMergeJoinIT extends BaseHBaseManagedTimeIT { " SERVER SORTED BY [\"O.item_id\"]\n" + " CLIENT MERGE SORT\n" + "CLIENT 4 ROW LIMIT", + + "SORT-MERGE-JOIN (INNER) TABLES\n" + + " CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_Join.ItemTable [-32768]\n" + + " SERVER FILTER BY FIRST KEY ONLY\n" + + " SERVER SORTED BY [\"I1.:item_id\"]\n" + + " CLIENT MERGE SORT\n" + + "AND\n" + + " CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_Join.ItemTable [-32768]\n" + + " SERVER FILTER BY FIRST KEY ONLY\n" + + " SERVER SORTED BY [\"I2.:item_id\"]\n" + + " CLIENT MERGE SORT\n" + + "CLIENT SORTED BY [\"I1.:item_id\"]" }}); return testCases; } @@ -1674,6 +1702,9 @@ public class SortMergeJoinIT extends BaseHBaseManagedTimeIT { assertFalse(rs.next()); + rs = conn.createStatement().executeQuery("EXPLAIN " + query1); + assertEquals(plans[2], QueryUtil.getExplainPlan(rs)); + statement = conn.prepareStatement(query2); rs = statement.executeQuery(); assertTrue (rs.next()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/ea91e634/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java index cb9f4b1..f3b6bce 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java @@ -114,8 +114,6 @@ public class SubqueryUsingSortMergeJoinIT extends BaseHBaseManagedTimeIT { " CLIENT MERGE SORT\n" + " AND\n" + " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_DISPLAY_NAME + "\n" + - " SERVER SORTED BY [\"S.supplier_id\"]\n" + - " CLIENT MERGE SORT\n" + " CLIENT SORTED BY [\"I.item_id\"]\n" + "AND (SKIP MERGE)\n" + " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + " ['000000000000001'] - [*]\n" + http://git-wip-us.apache.org/repos/asf/phoenix/blob/ea91e634/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java index 7275b64..0ae31f0 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java @@ -27,6 +27,7 @@ import org.apache.phoenix.compile.GroupByCompiler.GroupBy; import org.apache.phoenix.compile.OrderPreservingTracker.Ordering; import org.apache.phoenix.exception.SQLExceptionCode; import org.apache.phoenix.exception.SQLExceptionInfo; +import org.apache.phoenix.execute.TupleProjector; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.OrderByExpression; import org.apache.phoenix.parse.LiteralParseNode; @@ -82,7 +83,8 @@ public class OrderByCompiler { public static OrderBy compile(StatementContext context, SelectStatement statement, GroupBy groupBy, Integer limit, - RowProjector projector, + RowProjector rowProjector, + TupleProjector tupleProjector, boolean isInRowKeyOrder) throws SQLException { List<OrderByNode> orderByNodes = statement.getOrderBy(); if (orderByNodes.isEmpty()) { @@ -91,19 +93,19 @@ public class OrderByCompiler { ExpressionCompiler compiler = new ExpressionCompiler(context, groupBy); // accumulate columns in ORDER BY OrderPreservingTracker tracker = - new OrderPreservingTracker(context, groupBy, Ordering.ORDERED, orderByNodes.size()); + new OrderPreservingTracker(context, groupBy, Ordering.ORDERED, orderByNodes.size(), tupleProjector); LinkedHashSet<OrderByExpression> orderByExpressions = Sets.newLinkedHashSetWithExpectedSize(orderByNodes.size()); for (OrderByNode node : orderByNodes) { ParseNode parseNode = node.getNode(); Expression expression = null; if (parseNode instanceof LiteralParseNode && ((LiteralParseNode)parseNode).getType() == PInteger.INSTANCE){ Integer index = (Integer)((LiteralParseNode)parseNode).getValue(); - int size = projector.getColumnProjectors().size(); + int size = rowProjector.getColumnProjectors().size(); if (index > size || index <= 0 ) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.PARAM_INDEX_OUT_OF_BOUND) .build().buildException(); } - expression = projector.getColumnProjector(index-1).getExpression(); + expression = rowProjector.getColumnProjector(index-1).getExpression(); } else { expression = node.getNode().accept(compiler); // Detect mix of aggregate and non aggregates (i.e. ORDER BY txns, SUM(txns) http://git-wip-us.apache.org/repos/asf/phoenix/blob/ea91e634/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java index 4191da9..f14d808 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java @@ -242,10 +242,11 @@ public class QueryCompiler { if (!table.isSubselect()) { context.setCurrentTable(table.getTableRef()); PTable projectedTable = table.createProjectedTable(!projectPKColumns, context); - TupleProjector.serializeProjectorIntoScan(context.getScan(), new TupleProjector(projectedTable)); + TupleProjector projector = new TupleProjector(projectedTable); + TupleProjector.serializeProjectorIntoScan(context.getScan(), projector); context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable, context.getConnection(), subquery.getUdfParseNodes())); table.projectColumns(context.getScan()); - return compileSingleQuery(context, subquery, binds, asSubquery, !asSubquery); + return compileSingleFlatQuery(context, subquery, binds, asSubquery, !asSubquery, null, projectPKColumns ? projector : null, true); } QueryPlan plan = compileSubquery(subquery, false); PTable projectedTable = table.createProjectedTable(plan.getProjector()); @@ -314,7 +315,7 @@ public class QueryCompiler { subPlans[i] = new HashSubPlan(i, joinPlan, optimized ? null : hashExpressions, joinSpec.isSingleValueOnly(), keyRangeLhsExpression, keyRangeRhsExpression); } TupleProjector.serializeProjectorIntoScan(context.getScan(), tupleProjector); - QueryPlan plan = compileSingleQuery(context, query, binds, asSubquery, !asSubquery && joinTable.isAllLeftJoin()); + QueryPlan plan = compileSingleFlatQuery(context, query, binds, asSubquery, !asSubquery && joinTable.isAllLeftJoin(), null, !table.isSubselect() && projectPKColumns ? tupleProjector : null, true); Expression postJoinFilterExpression = joinTable.compilePostFilterExpression(context, table); Integer limit = null; if (!query.isAggregate() && !query.isDistinct() && query.getOrderBy().isEmpty()) { @@ -368,7 +369,7 @@ public class QueryCompiler { PTable projectedTable = needsMerge ? JoinCompiler.joinProjectedTables(rhsProjTable, lhsTable, type == JoinType.Right ? JoinType.Left : type) : rhsProjTable; TupleProjector.serializeProjectorIntoScan(context.getScan(), tupleProjector); context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable, context.getConnection(), rhs.getUdfParseNodes())); - QueryPlan rhsPlan = compileSingleQuery(context, rhs, binds, asSubquery, !asSubquery && type == JoinType.Right); + QueryPlan rhsPlan = compileSingleFlatQuery(context, rhs, binds, asSubquery, !asSubquery && type == JoinType.Right, null, !rhsTable.isSubselect() && projectPKColumns ? tupleProjector : null, true); Expression postJoinFilterExpression = joinTable.compilePostFilterExpression(context, rhsTable); Integer limit = null; if (!rhs.isAggregate() && !rhs.isDistinct() && rhs.getOrderBy().isEmpty()) { @@ -536,7 +537,7 @@ public class QueryCompiler { Expression where = WhereCompiler.compile(context, select, viewWhere, subqueries); context.setResolver(resolver); // recover resolver RowProjector projector = ProjectionCompiler.compile(context, select, groupBy, asSubquery ? Collections.<PDatum>emptyList() : targetColumns); - OrderBy orderBy = OrderByCompiler.compile(context, select, groupBy, limit, projector, isInRowKeyOrder); + OrderBy orderBy = OrderByCompiler.compile(context, select, groupBy, limit, projector, groupBy == GroupBy.EMPTY_GROUP_BY ? innerPlanTupleProjector : null, isInRowKeyOrder); // Final step is to build the query plan if (!asSubquery) { int maxRows = statement.getMaxRows();