You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by la...@apache.org on 2019/12/24 14:26:47 UTC

[phoenix] branch 4.x-HBase-1.4 updated: PHOENIX-5096 Local index region pruning is not working as expected.

This is an automated email from the ASF dual-hosted git repository.

larsh pushed a commit to branch 4.x-HBase-1.4
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/4.x-HBase-1.4 by this push:
     new 2f9ad87  PHOENIX-5096 Local index region pruning is not working as expected.
2f9ad87 is described below

commit 2f9ad87e1c7d3ad879af490f2546a596516d2ccb
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" +