This is an automated email from the ASF dual-hosted git repository. larsh pushed a commit to branch 4.x-HBase-1.5 in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/4.x-HBase-1.5 by this push: new 1620c7d PHOENIX-5096 Local index region pruning is not working as expected. 1620c7d is described below commit 1620c7d7f6b8ce8ccf38e27e6bff1182ec6f7985 Author: Lars Hofhansl <la...@apache.org> AuthorDate: Tue Dec 24 06:26:39 2019 -0800 PHOENIX-5096 Local index region pruning is not working as expected. --- .../phoenix/iterate/BaseResultIterators.java | 9 ++++ .../apache/phoenix/compile/QueryCompilerTest.java | 60 ++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java index 45b4d4d..2dcc88b 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java @@ -1023,6 +1023,15 @@ public abstract class BaseResultIterators extends ExplainTable implements Result endKey = regionBoundaries.get(regionIndex); } if (isLocalIndex) { + if (dataPlan != null && dataPlan.getTableRef().getTable().getType() != PTableType.INDEX) { // Sanity check + ScanRanges dataScanRanges = dataPlan.getContext().getScanRanges(); + // we can skip a region completely for local indexes if the data plan does not intersect + if (!dataScanRanges.intersectRegion(regionInfo.getStartKey(), regionInfo.getEndKey(), false)) { + currentKeyBytes = endKey; + regionIndex++; + continue; + } + } // Only attempt further pruning if the prefix range is using // a skip scan since we've already pruned the range of regions // based on the start/stop key. diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java index e6337fa..b49aaf8 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java @@ -4870,6 +4870,66 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest { } @Test + public void testLocalIndexRegionPruning() throws SQLException { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + try (Connection conn = DriverManager.getConnection(getUrl(), props)) { + conn.createStatement().execute("CREATE TABLE T (\n" + + " A CHAR(1) NOT NULL,\n" + + " B CHAR(1) NOT NULL,\n" + + " C CHAR(1) NOT NULL,\n" + + " D CHAR(1),\n" + + " CONSTRAINT PK PRIMARY KEY (\n" + + " A,\n" + + " B,\n" + + " C\n" + + " )\n" + + ") SPLIT ON ('A','C','E','G','I')"); + + conn.createStatement().execute("CREATE LOCAL INDEX IDX ON T(D)"); + + // un-pruned, need to scan all six regions + String query = "SELECT * FROM T WHERE D = 'C'"; + PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); + QueryPlan plan = statement.optimizeQuery(query); + assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); + plan.iterator(); + assertEquals(6, plan.getScans().size()); + + // fixing first part of the key, can limit scanning to two regions + query = "SELECT * FROM T WHERE A = 'A' AND D = 'C'"; + statement = conn.createStatement().unwrap(PhoenixStatement.class); + plan = statement.optimizeQuery(query); + assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); + plan.iterator(); + assertEquals(2, plan.getScans().size()); + + // same with skipscan filter + query = "SELECT * FROM T WHERE A IN ('A', 'C') AND D = 'C'"; + statement = conn.createStatement().unwrap(PhoenixStatement.class); + plan = statement.optimizeQuery(query); + assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); + plan.iterator(); + assertEquals(3, plan.getScans().size()); + + // two parts of key fixed, need to scan a single region only + query = "SELECT * FROM T WHERE A = 'A' AND B = 'A' AND D = 'C'"; + statement = conn.createStatement().unwrap(PhoenixStatement.class); + plan = statement.optimizeQuery(query); + assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); + plan.iterator(); + assertEquals(1, plan.getScans().size()); + + // same with skipscan filter + query = "SELECT * FROM T WHERE A IN ('A', 'C') AND B = 'A' AND D = 'C'"; + statement = conn.createStatement().unwrap(PhoenixStatement.class); + plan = statement.optimizeQuery(query); + assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); + plan.iterator(); + assertEquals(2, plan.getScans().size()); + } + } + + @Test public void testSmallScanForPointLookups() throws SQLException { Properties props = PropertiesUtil.deepCopy(new Properties()); createTestTable(getUrl(), "CREATE TABLE FOO(\n" +